nfs4: Use semaphore to cancel threads instead of interrupt_thread()
This commit is contained in:
parent
9054c96c17
commit
92284dcc2c
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -53,6 +53,7 @@ protected:
|
|||
Transport proto);
|
||||
status_t _Connect();
|
||||
|
||||
sem_id fWaitCancel;
|
||||
int fSock;
|
||||
mutex fSockLock;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -45,6 +45,7 @@ private:
|
|||
static status_t _RenewalThreadStart(void* ptr);
|
||||
thread_id fThread;
|
||||
bool fThreadCancel;
|
||||
sem_id fWaitCancel;
|
||||
|
||||
uint32 fLeaseTime;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue