src/core/sentinel.c File Reference

Sentinel manager implementation. More...

#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include <unistd.h>
#include <stddef.h>
#include <misc/result.h>
#include <misc/pool.h>
#include <misc/malloc.h>
#include <misc/debug.h>
#include <misc/mutex.h>
#include <core/config.h>
#include <core/sentinel.h>
#include <core/tx.h>
#include <core/txdesc.h>

Go to the source code of this file.

Classes

struct  txc_sentinel_s
struct  txc_sentinel_list_entry_s
struct  txc_sentinel_list_s
struct  txc_sentinelmgr_s

Defines

#define TXC_SENTINEL_NOOWNER   0x0

Functions

txc_result_t txc_sentinelmgr_create (txc_sentinelmgr_t **sentinelmgrp)
 Creates a sentinel manager.
void txc_sentinelmgr_destroy (txc_sentinelmgr_t **sentinelmgrp)
 Destroys a sentinel manager.
txc_result_t txc_sentinel_create (txc_sentinelmgr_t *sentinelmgr, txc_sentinel_t **sentinelp)
void txc_sentinel_destroy (txc_sentinel_t *sentinel)
 Destroys a sentinel.
txc_result_t txc_sentinel_detach (txc_sentinel_t *sentinel)
 Detaches from a sentinel.
void txc_sentinel_register_sentinelmgr_commit_action (txc_tx_t *txd)
void txc_sentinel_register_sentinelmgr_undo_action (txc_tx_t *txd)
void txc_sentinel_transaction_postbegin (txc_tx_t *txd)
txc_result_t txc_sentinel_list_create (txc_sentinelmgr_t *sentinelmgr, txc_sentinel_list_t **sentinel_list)
 Create a sentinel list.
txc_result_t txc_sentinel_list_init (txc_sentinel_list_t *sentinel_list)
 Initialize a sentinel list.
txc_result_t txc_sentinel_list_destroy (txc_sentinel_list_t **sentinel_list)
 Destroy a sentinel list.
txc_result_t txc_sentinel_enlist (txc_tx_t *txd, txc_sentinel_t *sentinel, int flags)
 Enlist the sentinel in the transaction's sentinel list.
txc_result_t txc_sentinel_tryacquire (txc_tx_t *txd, txc_sentinel_t *sentinel, int flags)
 Try to acquire a sentinel.
void txc_sentinelmgr_print_pools (txc_sentinelmgr_t *sentinelmgr)
txc_tx_ttxc_sentinel_owner (txc_sentinel_t *sentinel)
txc_result_t txc_sentinel_is_enlisted (txc_tx_t *txd, txc_sentinel_t *sentinel)

Variables

txc_sentinelmgr_ttxc_g_sentinelmgr


Detailed Description

Sentinel manager implementation.

Sentinels overview

Most transactional memory systems operate only at user level and do not isolate changes to kernel data made within a transaction. For example, a thread may view speculative data written to a file by a transaction that later aborts. Such transient effects do not occur with locks and may cause the program to behave incorrectly.

The xCall interface provides isolation for kernel objects with sentinels. A sentinel is a lightweight, revocable user-level lock for a kernel object. The purpose of a sentinel is to isolate the effects of system calls from other threads in the same process. Similar to a database lock, sentinels are centrally managed to detect deadlocks and can be revoked to recover from deadlocks.

The xCall APIs associate sentinels with distinct kernel objects, such as sockets and file descriptors. Sentinels are released only when the transaction commits or aborts to implement two-phase locking. However, sentinels do not protect programs with inherent race conditions, such as when a non-transactional thread reads data from a file written by a transaction.

Before invoking a system call, an xCall acquires the sentinel that isolates the underlying kernel object accessed by the call. Sentinels only lock the logical state of the kernel that is visible through system calls. Internally, kernel queues and buffers may have different contents as long as system calls do not observe a change.

The sentinel implementation must detect deadlock when two transactions acquire the same set of sentinels concurrently in different orders. On deadlock, one transaction aborts and releases its sentinels

Implementation

The sentinel manager subsystem allocates and maps sentinels to logical kernel objects (KOA) in user mode. We implement process-wide sentinels with POSIX mutex locks.

The manager maintains lists of the sentinels acquired by each transaction and releases them at commit or abort. The sentinel list is actually kept in the transaction's descriptor but managed by the sentinel manager. The sentinel manager is informed about commit/abort/retry events indirectly by registering commit/undo actions. This allows to incrementally pay the cost when the transaction acquires any sentinels.

To prevent deadlocks, the sentinel manager enforces a canonical global order over all sentinels based on the sentinel’s index in the global table of allocated sentinels. When a transaction cannot acquire a sentinel, the sentinel manager aborts the transaction and releases the acquired sentinels. The transaction reacquires all the sentinels it encountered in canonical order before restarting. The transaction holds on to the sentinels until commit, even if it does not require the same sentinels when reexecuted.

Attach/Detach operations:

Whenever creating and enlisting a sentinel, we logically attach to the sentinel by calling sentinel_attach. Attaching to a sentinel increments the sentinel's reference counter by one. Whenever releasing a sentinel, we logically detach from the sentinel by calling sentinel_detach. Detaching from a sentinel decrements the sentinel's reference counter by one. Attach and detach operations prevent someone from destroying the sentinel as long as there are transactions interested in the sentinel. Here are some races which are prevented through this scheme:

Here is how our scheme prevents such races. A sentinel is only destroyed when its reference counter reaches to zero and we release the sentinel of a KOA we created after we destroy the KOA. Someone who sees the KOA may also attach to the sentinel if interested. This is done atomically. So when you release sentinels, and detach from them is guaranteed that someone interested in the sentinel would have a valid reference to it. Of course the sentinel at that time protects no object which is fine. What we really avoid is the sentinel to protect another KOA between the time we see a KOA and we acquire the sentinel.

Definition in file sentinel.c.


Function Documentation

void txc_sentinel_destroy ( txc_sentinel_t sentinel  ) 

Destroys a sentinel.

Parameters:
[in] sentinel The sentinel to destroy (deallocate).

Definition at line 252 of file sentinel.c.

References txc_sentinel_s::synch_mutex, TXC_ASSERT, TXC_MUTEX_LOCK, and TXC_MUTEX_UNLOCK.

txc_result_t txc_sentinel_detach ( txc_sentinel_t sentinel  ) 

Detaches from a sentinel.

It logically detaches from the sentinel by decrementing the sentinel's refererence counter. If reference counter becomes zero then sentinel is destroyed.

Parameters:
[in] sentinel The sentinel to detach from.
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 294 of file sentinel.c.

References txc_sentinel_s::synch_mutex, TXC_MUTEX_LOCK, and TXC_MUTEX_UNLOCK.

Referenced by txc_koa_destroy().

txc_result_t txc_sentinel_enlist ( txc_tx_t txd,
txc_sentinel_t sentinel,
int  flags 
)

Enlist the sentinel in the transaction's sentinel list.

It also attaches to the sentinel by bumping up the sentinel's refcount via a call to sentinel_attach().

Parameters:
[in] txd Transactional descriptor.
[in] sentinel Sentinel to enlist.
[in] flags TXC_SENTINEL_ACQUIREONRETRY
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 730 of file sentinel.c.

References txc_tx_s::sentinel_list, txc_sentinel_s::synch_mutex, TXC_MUTEX_LOCK, TXC_MUTEX_UNLOCK, TXC_R_SUCCESS, and TXC_SENTINEL_ACQUIREONRETRY.

txc_result_t txc_sentinel_list_create ( txc_sentinelmgr_t sentinelmgr,
txc_sentinel_list_t **  sentinel_list 
)

Create a sentinel list.

Parameters:
[in] sentinelmgr Sentinel manager responsible for the sentinel list.
[in,out] sentinel_list Pointer to the created sentinel list.
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 618 of file sentinel.c.

References FREE, MALLOC, TXC_R_NOMEMORY, TXC_R_SUCCESS, and TXC_SENTINEL_LIST_SIZE.

Referenced by txc_txmgr_create().

txc_result_t txc_sentinel_list_destroy ( txc_sentinel_list_t **  sentinel_list  ) 

Destroy a sentinel list.

Deallocate sentinel list entries and then deallocates the list itself

Parameters:
[in,out] sentinel_list Pointer to the sentinel list to deallocate. Pointer will point to NULL after return.
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 669 of file sentinel.c.

References FREE, and TXC_R_SUCCESS.

Referenced by txc_txmgr_destroy().

txc_result_t txc_sentinel_list_init ( txc_sentinel_list_t sentinel_list  ) 

Initialize a sentinel list.

Parameters:
[in] sentinel_list Sentinel list to deallocate.
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 651 of file sentinel.c.

References txc_sentinel_list_s::num_entries, and TXC_R_SUCCESS.

Referenced by txc_tx_create().

txc_result_t txc_sentinel_tryacquire ( txc_tx_t txd,
txc_sentinel_t sentinel,
int  flags 
)

Try to acquire a sentinel.

It will try to acquire the sentinel. If sentinel is acquired it will enlist it in the transaction's sentinel list as acquired, otherwise if the sentinel is not acquired (busy) it will return without block-waiting for the sentinel to become free (prevent deadlock).

Parameters:
[in] txd Transactional descriptor.
[in] sentinel Sentinel to acquire.
[in] flags TXC_SENTINEL_ACQUIRED, TXC_SENTINEL_ACQUIREONRETRY
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 759 of file sentinel.c.

References txc_sentinel_s::id, txc_sentinel_s::owner, txc_sentinel_s::sentinel_mutex, txc_sentinel_s::synch_mutex, TXC_ASSERT, TXC_DEBUG_PRINT, TXC_INTERNALERROR, TXC_MUTEX_LOCK, TXC_MUTEX_TRYLOCK, TXC_MUTEX_UNLOCK, TXC_R_BUSYSENTINEL, TXC_R_SUCCESS, txc_runtime_settings, TXC_SENTINEL_ACQUIREONRETRY, txc_sentinel_is_enlisted(), txc_sentinel_owner(), and txc_tx_get_xactstate().

Referenced by x_close(), x_create(), x_dup(), x_fsync(), x_lseek(), x_open(), x_pipe(), x_read(), x_rename(), x_sendmsg(), x_socket(), x_unlink(), and x_write_pipe().

txc_result_t txc_sentinelmgr_create ( txc_sentinelmgr_t **  sentinelmgrp  ) 

Creates a sentinel manager.

It preallocates a pool of sentinels to make sentinel allocation fast.

Parameters:
[out] sentinelmgrp Pointer to the created sentinel manager.
Returns:
Code indicating success or failure (reason) of the operation.

Definition at line 158 of file sentinel.c.

References FREE, txc_sentinel_s::id, MALLOC, txc_sentinel_s::manager, txc_sentinel_s::owner, txc_sentinel_s::sentinel_mutex, txc_sentinel_s::synch_mutex, TXC_MUTEX_INIT, txc_pool_create(), TXC_POOL_OBJECT_ALLOCATED, txc_pool_object_first(), TXC_POOL_OBJECT_FREE, txc_pool_object_next(), txc_pool_object_of(), TXC_R_NOMEMORY, TXC_R_SUCCESS, TXC_SENTINEL_NOOWNER, and TXC_SENTINEL_NUM.

Referenced by _TXC_global_init().

void txc_sentinelmgr_destroy ( txc_sentinelmgr_t **  sentinelmgrp  ) 

Destroys a sentinel manager.

It deallocates all sentinels that it manages.

Parameters:
[in,out] sentinelmgrp Poitner to the sentinel manager to be destroyed.

Definition at line 206 of file sentinel.c.

References FREE, and txc_pool_destroy().


Generated on Wed Dec 9 20:32:40 2009 for xCalls by  doxygen 1.4.7