From 92284dcc2cc283de8cf553889891ae46aa2ba991 Mon Sep 17 00:00:00 2001 From: Pawel Dziepak Date: Sun, 8 Jul 2012 23:33:44 +0200 Subject: [PATCH] nfs4: Use semaphore to cancel threads instead of interrupt_thread() --- headers/os/drivers/KernelExport.h | 1 - .../kernel/file_systems/nfs4/Connection.cpp | 44 +++++++++++++++++++ .../kernel/file_systems/nfs4/Connection.h | 1 + .../kernel/file_systems/nfs4/NFS4Server.cpp | 12 +++-- .../kernel/file_systems/nfs4/NFS4Server.h | 1 + .../kernel/file_systems/nfs4/RPCServer.cpp | 6 +-- src/system/kernel/thread.cpp | 14 ------ 7 files changed, 57 insertions(+), 22 deletions(-) diff --git a/headers/os/drivers/KernelExport.h b/headers/os/drivers/KernelExport.h index 14c707dc66..3e2e5848dd 100644 --- a/headers/os/drivers/KernelExport.h +++ b/headers/os/drivers/KernelExport.h @@ -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); diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp index 6a94ba7788..f7381c747f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.cpp @@ -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); diff --git a/src/add-ons/kernel/file_systems/nfs4/Connection.h b/src/add-ons/kernel/file_systems/nfs4/Connection.h index 51d0323db2..eff2a6673f 100644 --- a/src/add-ons/kernel/file_systems/nfs4/Connection.h +++ b/src/add-ons/kernel/file_systems/nfs4/Connection.h @@ -53,6 +53,7 @@ protected: Transport proto); status_t _Connect(); + sem_id fWaitCancel; int fSock; mutex fSockLock; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp index 49886ef592..70757d34df 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.cpp @@ -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; diff --git a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h index 2979923bb4..fdf61e88b8 100644 --- a/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h +++ b/src/add-ons/kernel/file_systems/nfs4/NFS4Server.h @@ -45,6 +45,7 @@ private: static status_t _RenewalThreadStart(void* ptr); thread_id fThread; bool fThreadCancel; + sem_id fWaitCancel; uint32 fLeaseTime; diff --git a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp index 3230caa172..5e017149ad 100644 --- a/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp +++ b/src/add-ons/kernel/file_systems/nfs4/RPCServer.cpp @@ -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) diff --git a/src/system/kernel/thread.cpp b/src/system/kernel/thread.cpp index 022b8a1173..6c95268c44 100644 --- a/src/system/kernel/thread.cpp +++ b/src/system/kernel/thread.cpp @@ -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 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) {