session: slot table uses SleepConditionVariableCS
changed nfs41_slot_table.lock and .cond to a CRITICAL_SECTION and CONDITION_VARIABLE for use with SleepConditionVariableCS() added a 'num_used' field to simplify the condition variable's predicate function slot_table_avail() Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
This commit is contained in:
parent
54551655d0
commit
94fc1d946c
2 changed files with 82 additions and 148 deletions
|
|
@ -221,8 +221,9 @@ typedef struct __nfs41_slot_table {
|
||||||
uint32_t used_slots[NFS41_MAX_NUM_SLOTS];
|
uint32_t used_slots[NFS41_MAX_NUM_SLOTS];
|
||||||
uint32_t max_slots;
|
uint32_t max_slots;
|
||||||
uint32_t highest_used;
|
uint32_t highest_used;
|
||||||
HANDLE lock;
|
uint32_t num_used;
|
||||||
HANDLE cond;
|
CRITICAL_SECTION lock;
|
||||||
|
CONDITION_VARIABLE cond;
|
||||||
} nfs41_slot_table;
|
} nfs41_slot_table;
|
||||||
|
|
||||||
typedef struct __nfs41_channel_attrs {
|
typedef struct __nfs41_channel_attrs {
|
||||||
|
|
|
||||||
|
|
@ -29,86 +29,45 @@
|
||||||
#include "daemon_debug.h"
|
#include "daemon_debug.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* predicate for nfs41_slot_table.cond */
|
||||||
|
static int slot_table_avail(
|
||||||
|
IN const nfs41_slot_table *table)
|
||||||
|
{
|
||||||
|
return table->num_used < table->max_slots;
|
||||||
|
}
|
||||||
|
|
||||||
/* session slot mechanism */
|
/* session slot mechanism */
|
||||||
static int init_slot_table(nfs41_slot_table *table)
|
static void init_slot_table(nfs41_slot_table *table)
|
||||||
{
|
{
|
||||||
int i, status = 0;
|
uint32_t i;
|
||||||
|
EnterCriticalSection(&table->lock);
|
||||||
//initialize slot table lock
|
|
||||||
table->lock = CreateMutex(NULL, FALSE, NULL);
|
|
||||||
if (table->lock == NULL) {
|
|
||||||
status = GetLastError();
|
|
||||||
eprintf("init_slot_table: CreateMutex failed %d\n", status);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
//initialize condition variable for slots
|
|
||||||
table->cond = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
||||||
if (table->cond == NULL) {
|
|
||||||
status = GetLastError();
|
|
||||||
eprintf("init_slot_table: CreateEvent failed %d\n", status);
|
|
||||||
goto out_mutex;
|
|
||||||
}
|
|
||||||
|
|
||||||
table->max_slots = NFS41_MAX_NUM_SLOTS;
|
table->max_slots = NFS41_MAX_NUM_SLOTS;
|
||||||
for(i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
|
for (i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
|
||||||
table->seq_nums[i] = 1;
|
table->seq_nums[i] = 1;
|
||||||
table->used_slots[i] = 0;
|
table->used_slots[i] = 0;
|
||||||
}
|
}
|
||||||
table->highest_used = 0;
|
table->highest_used = table->num_used = 0;
|
||||||
out:
|
|
||||||
return status;
|
|
||||||
out_mutex:
|
|
||||||
CloseHandle(table->lock);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int reinit_slot_table(nfs41_slot_table *table)
|
/* wake any threads waiting on a slot */
|
||||||
{
|
if (slot_table_avail(table))
|
||||||
int i, status = 0;
|
WakeAllConditionVariable(&table->cond);
|
||||||
|
LeaveCriticalSection(&table->lock);
|
||||||
status = WaitForSingleObject(table->lock, INFINITE);
|
|
||||||
if (status != WAIT_OBJECT_0) {
|
|
||||||
dprintf(1, "reinit_slot_table: WaitForSingleObject failed\n");
|
|
||||||
print_condwait_status(1, status);
|
|
||||||
status = ERROR_LOCK_VIOLATION;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
table->max_slots = NFS41_MAX_NUM_SLOTS;
|
|
||||||
for(i = 0; i < NFS41_MAX_NUM_SLOTS; i++) {
|
|
||||||
table->seq_nums[i] = 1;
|
|
||||||
table->used_slots[i] = 0;
|
|
||||||
}
|
|
||||||
table->highest_used = 0;
|
|
||||||
SetEvent(table->cond);
|
|
||||||
ReleaseMutex(table->lock);
|
|
||||||
out:
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_slot_table(nfs41_slot_table *table)
|
|
||||||
{
|
|
||||||
CloseHandle(table->lock);
|
|
||||||
CloseHandle(table->cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nfs41_session_bump_seq(
|
int nfs41_session_bump_seq(
|
||||||
IN nfs41_session *session,
|
IN nfs41_session *session,
|
||||||
IN uint32_t slotid)
|
IN uint32_t slotid)
|
||||||
{
|
{
|
||||||
int status;
|
nfs41_slot_table *table = &session->table;
|
||||||
|
int status = NO_ERROR;
|
||||||
|
|
||||||
AcquireSRWLockShared(&session->client->session_lock);
|
AcquireSRWLockShared(&session->client->session_lock);
|
||||||
status = WaitForSingleObject(session->table.lock, INFINITE);
|
EnterCriticalSection(&table->lock);
|
||||||
if (status != WAIT_OBJECT_0) {
|
|
||||||
dprintf(1, "nfs41_session_bump_seq: WaitForSingleObject failed\n");
|
if (slotid < NFS41_MAX_NUM_SLOTS)
|
||||||
print_condwait_status(1, status);
|
table->seq_nums[slotid]++;
|
||||||
status = ERROR_LOCK_VIOLATION;
|
|
||||||
goto out;
|
LeaveCriticalSection(&table->lock);
|
||||||
}
|
|
||||||
session->table.seq_nums[slotid]++;
|
|
||||||
ReleaseMutex(session->table.lock);
|
|
||||||
out:
|
|
||||||
ReleaseSRWLockShared(&session->client->session_lock);
|
ReleaseSRWLockShared(&session->client->session_lock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -117,30 +76,30 @@ int nfs41_session_free_slot(
|
||||||
IN nfs41_session *session,
|
IN nfs41_session *session,
|
||||||
IN uint32_t slotid)
|
IN uint32_t slotid)
|
||||||
{
|
{
|
||||||
int status, i;
|
nfs41_slot_table *table = &session->table;
|
||||||
|
int status = NO_ERROR;
|
||||||
|
|
||||||
AcquireSRWLockShared(&session->client->session_lock);
|
AcquireSRWLockShared(&session->client->session_lock);
|
||||||
status = WaitForSingleObject(session->table.lock, INFINITE);
|
EnterCriticalSection(&table->lock);
|
||||||
if (status != WAIT_OBJECT_0) {
|
|
||||||
dprintf(1, "nfs41_session_free_slot: WaitForSingleObject failed\n");
|
/* flag the slot as unused */
|
||||||
print_condwait_status(1, status);
|
if (slotid < NFS41_MAX_NUM_SLOTS && table->used_slots[slotid]) {
|
||||||
status = ERROR_LOCK_VIOLATION;
|
table->used_slots[slotid] = 0;
|
||||||
goto out;
|
table->num_used--;
|
||||||
}
|
}
|
||||||
session->table.used_slots[slotid] = 0;
|
/* update highest_used if necessary */
|
||||||
if (slotid == session->table.highest_used) {
|
if (slotid == table->highest_used) {
|
||||||
session->table.highest_used = 0;
|
while (table->highest_used && !table->used_slots[table->highest_used])
|
||||||
for (i = slotid; i > 0; i--) {
|
table->highest_used--;
|
||||||
if (session->table.used_slots[i]) {
|
|
||||||
session->table.highest_used = i;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
dprintf(3, "freeing slot#=%d used=%d highest=%d\n",
|
||||||
}
|
slotid, table->num_used, table->highest_used);
|
||||||
dprintf(3, "freeing slot#=%d highest=%d\n", slotid, session->table.highest_used);
|
|
||||||
SetEvent(session->table.cond);
|
/* wake any threads waiting on a slot */
|
||||||
ReleaseMutex(session->table.lock);
|
if (slot_table_avail(table))
|
||||||
out:
|
WakeAllConditionVariable(&table->cond);
|
||||||
|
|
||||||
|
LeaveCriticalSection(&table->lock);
|
||||||
ReleaseSRWLockShared(&session->client->session_lock);
|
ReleaseSRWLockShared(&session->client->session_lock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -148,56 +107,39 @@ out:
|
||||||
int nfs41_session_get_slot(
|
int nfs41_session_get_slot(
|
||||||
IN nfs41_session *session,
|
IN nfs41_session *session,
|
||||||
OUT uint32_t *slot,
|
OUT uint32_t *slot,
|
||||||
OUT uint32_t *seq,
|
OUT uint32_t *seqid,
|
||||||
OUT uint32_t *highest)
|
OUT uint32_t *highest)
|
||||||
{
|
{
|
||||||
uint32_t status = NO_ERROR;
|
nfs41_slot_table *table = &session->table;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
int status = NO_ERROR;
|
||||||
|
|
||||||
AcquireSRWLockShared(&session->client->session_lock);
|
AcquireSRWLockShared(&session->client->session_lock);
|
||||||
look_for_slot:
|
EnterCriticalSection(&table->lock);
|
||||||
status = WaitForSingleObject(session->table.lock, INFINITE);
|
|
||||||
if (status != WAIT_OBJECT_0) {
|
/* wait for an available slot */
|
||||||
eprintf("nfs41_session_get_slot: WaitForSingleObject failed with %d\n",
|
while (!slot_table_avail(table))
|
||||||
status);
|
SleepConditionVariableCS(&table->cond, &table->lock, INFINITE);
|
||||||
print_condwait_status(1, status);
|
|
||||||
status = ERROR_LOCK_VIOLATION;
|
for (i = 0; i < table->max_slots; i++) {
|
||||||
goto out;
|
if (table->used_slots[i])
|
||||||
}
|
continue;
|
||||||
dprintf(3, "looking for a free slot in the slot table\n");
|
|
||||||
*highest = session->table.highest_used;
|
table->used_slots[i] = 1;
|
||||||
for (i = 0; i < session->table.max_slots; i++) {
|
table->num_used++;
|
||||||
if (!session->table.used_slots[i]) {
|
if (i > table->highest_used)
|
||||||
session->table.used_slots[i] = 1; // mark slot used
|
table->highest_used = i;
|
||||||
*slot = i; // return slot number
|
|
||||||
*seq = session->table.seq_nums[i]; // return sequence number for the slot
|
*slot = i;
|
||||||
//update highest_slot_used if needed
|
*seqid = table->seq_nums[i];
|
||||||
if (i > session->table.highest_used)
|
*highest = table->highest_used;
|
||||||
*highest = session->table.highest_used = i;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
LeaveCriticalSection(&table->lock);
|
||||||
if (i == session->table.max_slots) {
|
|
||||||
dprintf(1, "all (%d) slots are used. waiting for a free slot\n",
|
|
||||||
session->table.max_slots);
|
|
||||||
ReleaseMutex(session->table.lock);
|
|
||||||
status = WaitForSingleObject(session->table.cond, INFINITE);
|
|
||||||
if (status == WAIT_OBJECT_0) {
|
|
||||||
dprintf(1, "received a signal to look for a free slot\n");
|
|
||||||
ResetEvent(session->table.cond);
|
|
||||||
goto look_for_slot;
|
|
||||||
} else {
|
|
||||||
eprintf("nfs41_session_get_slot: WaitForSingleObject failed "
|
|
||||||
"with %d\n", status);
|
|
||||||
print_condwait_status(1, status);
|
|
||||||
status = ERROR_LOCK_VIOLATION;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ReleaseMutex(session->table.lock);
|
|
||||||
dprintf(2, "session %p: using slot#=%d with seq#=%d highest=%d\n", session, *slot, *seq, *highest);
|
|
||||||
out:
|
|
||||||
ReleaseSRWLockShared(&session->client->session_lock);
|
ReleaseSRWLockShared(&session->client->session_lock);
|
||||||
|
|
||||||
|
dprintf(2, "session %p: using slot#=%d with seq#=%d highest=%d\n",
|
||||||
|
session, *slot, *seqid, *highest);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -243,8 +185,8 @@ static int session_alloc(
|
||||||
IN nfs41_client *client,
|
IN nfs41_client *client,
|
||||||
OUT nfs41_session **session_out)
|
OUT nfs41_session **session_out)
|
||||||
{
|
{
|
||||||
int status;
|
|
||||||
nfs41_session *session;
|
nfs41_session *session;
|
||||||
|
int status = NO_ERROR;
|
||||||
|
|
||||||
session = calloc(1, sizeof(nfs41_session));
|
session = calloc(1, sizeof(nfs41_session));
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
|
|
@ -255,9 +197,10 @@ static int session_alloc(
|
||||||
session->renew_thread = INVALID_HANDLE_VALUE;
|
session->renew_thread = INVALID_HANDLE_VALUE;
|
||||||
session->isValidState = FALSE;
|
session->isValidState = FALSE;
|
||||||
|
|
||||||
status = init_slot_table(&session->table);
|
InitializeCriticalSection(&session->table.lock);
|
||||||
if (status)
|
InitializeConditionVariable(&session->table.cond);
|
||||||
goto out_err_session;
|
|
||||||
|
init_slot_table(&session->table);
|
||||||
|
|
||||||
//initialize session lock
|
//initialize session lock
|
||||||
InitializeSRWLock(&client->session_lock);
|
InitializeSRWLock(&client->session_lock);
|
||||||
|
|
@ -268,9 +211,6 @@ static int session_alloc(
|
||||||
*session_out = session;
|
*session_out = session;
|
||||||
out:
|
out:
|
||||||
return status;
|
return status;
|
||||||
out_err_session:
|
|
||||||
free(session);
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int nfs41_session_create(
|
int nfs41_session_create(
|
||||||
|
|
@ -320,16 +260,9 @@ int nfs41_session_renew(
|
||||||
|
|
||||||
AcquireSRWLockExclusive(&session->client->session_lock);
|
AcquireSRWLockExclusive(&session->client->session_lock);
|
||||||
session->cb_session.cb_seqnum = 0;
|
session->cb_session.cb_seqnum = 0;
|
||||||
status = reinit_slot_table(&session->table);
|
init_slot_table(&session->table);
|
||||||
if (status)
|
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
status = nfs41_create_session(session->client, session, FALSE);
|
status = nfs41_create_session(session->client, session, FALSE);
|
||||||
if (status) {
|
|
||||||
eprintf("nfs41_create_session failed %d\n", status);
|
|
||||||
goto out_unlock;
|
|
||||||
}
|
|
||||||
out_unlock:
|
|
||||||
ReleaseSRWLockExclusive(&session->client->session_lock);
|
ReleaseSRWLockExclusive(&session->client->session_lock);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
@ -380,7 +313,7 @@ void nfs41_session_free(
|
||||||
session->client->rpc->is_valid_session = FALSE;
|
session->client->rpc->is_valid_session = FALSE;
|
||||||
nfs41_destroy_session(session);
|
nfs41_destroy_session(session);
|
||||||
}
|
}
|
||||||
free_slot_table(&session->table);
|
DeleteCriticalSection(&session->table.lock);
|
||||||
ReleaseSRWLockExclusive(&session->client->session_lock);
|
ReleaseSRWLockExclusive(&session->client->session_lock);
|
||||||
free(session);
|
free(session);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue