nfs4: Use semaphore to cancel threads instead of interrupt_thread()

This commit is contained in:
Pawel Dziepak 2012-07-08 23:33:44 +02:00
parent 9054c96c17
commit 92284dcc2c
7 changed files with 57 additions and 22 deletions

View File

@ -138,7 +138,6 @@ extern bool cancel_timer(timer *t);
/* kernel threads */
extern thread_id spawn_kernel_thread(thread_func function,
const char *name, int32 priority, void *arg);
extern status_t interrupt_thread(thread_id id);
/* signal functions */
extern int send_signal_etc(pid_t thread, uint signal, uint32 flags);

View File

@ -88,6 +88,7 @@ ServerAddress::ResolveName(const char* name, ServerAddress* addr)
Connection::Connection(const sockaddr_in& addr, Transport proto)
:
fWaitCancel(create_sem(0, NULL)),
fSock(-1),
fProtocol(proto),
fServerAddress(addr)
@ -115,6 +116,7 @@ Connection::~Connection()
if (fSock != -1)
close(fSock);
mutex_destroy(&fSockLock);
delete_sem(fWaitCancel);
}
@ -192,7 +194,25 @@ ConnectionStream::Receive(void** pbuffer, uint32* psize)
int32 record_size;
bool last_one;
object_wait_info object[2];
object[0].object = fWaitCancel;
object[0].type = B_OBJECT_TYPE_SEMAPHORE;
object[0].events = B_EVENT_ACQUIRE_SEMAPHORE;
object[1].object = fSock;
object[1].type = B_OBJECT_TYPE_FD;
object[1].events = B_EVENT_READ;
do {
result = wait_for_objects(object, 2);
if (result < B_OK ||
(object[0].events & B_EVENT_ACQUIRE_SEMAPHORE) != 0) {
free(buffer);
return ECONNABORTED;
} else if ((object[1].events & B_EVENT_READ) == 0)
continue;
// There is only one listener thread per connection. No need to lock.
uint32 received = 0;
do {
@ -253,6 +273,26 @@ ConnectionPacket::Receive(void** pbuffer, uint32* psize)
if (buffer == NULL)
return B_NO_MEMORY;
object_wait_info object[2];
object[0].object = fWaitCancel;
object[0].type = B_OBJECT_TYPE_SEMAPHORE;
object[0].events = B_EVENT_ACQUIRE_SEMAPHORE;
object[1].object = fSock;
object[1].type = B_OBJECT_TYPE_FD;
object[1].events = B_EVENT_READ;
do {
result = wait_for_objects(object, 2);
if (result < B_OK ||
(object[0].events & B_EVENT_ACQUIRE_SEMAPHORE) != 0) {
free(buffer);
return ECONNABORTED;
} else if ((object[1].events & B_EVENT_READ) == 0)
continue;
break;
} while (true);
// There is only one listener thread per connection. No need to lock.
size = recv(fSock, buffer, size, 0);
if (size < 0) {
@ -333,7 +373,9 @@ Connection::_Connect()
status_t
Connection::Reconnect()
{
release_sem(fWaitCancel);
close(fSock);
acquire_sem(fWaitCancel);
return _Connect();
}
@ -341,6 +383,8 @@ Connection::Reconnect()
void
Connection::Disconnect()
{
release_sem(fWaitCancel);
int sock = fSock;
fSock = -1;
close(sock);

View File

@ -53,6 +53,7 @@ protected:
Transport proto);
status_t _Connect();
sem_id fWaitCancel;
int fSock;
mutex fSockLock;

View File

@ -16,6 +16,7 @@
NFS4Server::NFS4Server(RPC::Server* serv)
:
fThreadCancel(true),
fWaitCancel(create_sem(1, NULL)),
fLeaseTime(0),
fClientIdLastUse(0),
fUseCount(0),
@ -31,10 +32,11 @@ NFS4Server::~NFS4Server()
{
fThreadCancel = true;
fUseCount = 0;
interrupt_thread(fThread);
release_sem(fWaitCancel);
status_t result;
wait_for_thread(fThread, &result);
delete_sem(fWaitCancel);
mutex_destroy(&fClientIdLock);
mutex_destroy(&fFSLock);
}
@ -302,8 +304,12 @@ NFS4Server::_Renewal()
{
while (!fThreadCancel) {
// TODO: operations like OPEN, READ, CLOSE, etc also renew leases
snooze_etc(sSecToBigTime(fLeaseTime - 2), B_SYSTEM_TIMEBASE,
B_RELATIVE_TIMEOUT | B_CAN_INTERRUPT);
status_t result = acquire_sem_etc(fWaitCancel, 1,
B_RELATIVE_TIMEOUT, sSecToBigTime(fLeaseTime - 2));
if (result != B_TIMED_OUT) {
release_sem(fWaitCancel);
return B_OK;
}
uint64 clientId = fClientId;

View File

@ -45,6 +45,7 @@ private:
static status_t _RenewalThreadStart(void* ptr);
thread_id fThread;
bool fThreadCancel;
sem_id fWaitCancel;
uint32 fLeaseTime;

View File

@ -89,12 +89,11 @@ Server::~Server()
fThreadCancel = true;
fConnection->Disconnect();
interrupt_thread(fThread);
delete fConnection;
status_t result;
wait_for_thread(fThread, &result);
delete fConnection;
}
@ -205,7 +204,6 @@ status_t
Server::Repair()
{
fThreadCancel = true;
interrupt_thread(fThread);
status_t result = fConnection->Reconnect();
if (result != B_OK)

View File

@ -3007,20 +3007,6 @@ kill_thread(thread_id id)
}
status_t
interrupt_thread(thread_id id)
{
Thread* thread = Thread::GetAndLock(id);
if (thread == NULL)
return B_BAD_THREAD_ID;
BReference<Thread> threadReference(thread, true);
ThreadLocker threadLocker(thread, true);
InterruptsSpinLocker schedulerLocker(gSchedulerLock);
return thread_interrupt(thread, false);
}
status_t
send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize)
{