1/* 2 * Copyright 2001-2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "RequestThread.h" 7 8#include <new> 9 10#include <TLS.h> 11 12#include "FileSystem.h" 13#include "ServerDefs.h" 14#include "UserlandRequestHandler.h" 15#include "Volume.h" 16 17 18static const int32 sTLSVariable = tls_allocate(); 19 20 21// constructor 22RequestThreadContext::RequestThreadContext(Volume* volume, 23 KernelRequest* request) 24 : 25 fPreviousContext(NULL), 26 fThread(NULL), 27 fVolume(volume), 28 fRequest(request) 29{ 30 fThread = RequestThread::GetCurrentThread(); 31 if (fThread) { 32 fPreviousContext = fThread->GetContext(); 33 fThread->SetContext(this); 34 } 35 36 volume->GetFileSystem()->InitRequestThreadContext(this); 37} 38 39// destructor 40RequestThreadContext::~RequestThreadContext() 41{ 42 if (fThread) 43 fThread->SetContext(fPreviousContext); 44} 45 46// GetThread 47RequestThread* 48RequestThreadContext::GetThread() const 49{ 50 return fThread; 51} 52 53// GetVolume 54UserlandFS::Volume* 55RequestThreadContext::GetVolume() const 56{ 57 return fVolume; 58} 59 60 61// RequestThread 62 63// constructor 64RequestThread::RequestThread() 65 : fThread(-1), 66 fFileSystem(NULL), 67 fPort(NULL), 68 fContext(NULL), 69 fTerminating(false) 70{ 71} 72 73// destructor 74RequestThread::~RequestThread() 75{ 76 PrepareTermination(); 77 Terminate(); 78 delete fPort; 79} 80 81// Init 82status_t 83RequestThread::Init(FileSystem* fileSystem) 84{ 85 if (!fileSystem) 86 return B_BAD_VALUE; 87 // create the port 88 fPort = new(std::nothrow) RequestPort(kRequestPortSize); 89 if (!fPort) 90 return B_NO_MEMORY; 91 status_t error = fPort->InitCheck(); 92 if (error != B_OK) 93 return error; 94 // spawn the thread 95 fThread = spawn_thread(_ThreadEntry, "request thread", B_NORMAL_PRIORITY, 96 this); 97 if (fThread < 0) 98 return fThread; 99 fFileSystem = fileSystem; 100 return B_OK; 101} 102 103// Run 104void 105RequestThread::Run() 106{ 107 resume_thread(fThread); 108} 109 110// PrepareTermination 111void 112RequestThread::PrepareTermination() 113{ 114 if (fTerminating) 115 return; 116 fTerminating = true; 117 if (fPort) 118 fPort->Close(); 119} 120 121// Terminate 122void 123RequestThread::Terminate() 124{ 125 if (fThread >= 0) { 126 int32 result; 127 wait_for_thread(fThread, &result); 128 fThread = -1; 129 } 130} 131 132// GetPortInfo 133const Port::Info* 134RequestThread::GetPortInfo() const 135{ 136 return (fPort ? fPort->GetPortInfo() : NULL); 137} 138 139// GetFileSystem 140UserlandFS::FileSystem* 141RequestThread::GetFileSystem() const 142{ 143 return fFileSystem; 144} 145 146// GetPort 147RequestPort* 148RequestThread::GetPort() const 149{ 150 return fPort; 151} 152 153// GetContext 154RequestThreadContext* 155RequestThread::GetContext() const 156{ 157 return fContext; 158} 159 160// GetCurrentThread 161RequestThread* 162RequestThread::GetCurrentThread() 163{ 164 return (RequestThread*)tls_get(sTLSVariable); 165} 166 167// SetContext 168void 169RequestThread::SetContext(RequestThreadContext* context) 170{ 171 fContext = context; 172} 173 174// _ThreadEntry 175int32 176RequestThread::_ThreadEntry(void* data) 177{ 178 return ((RequestThread*)data)->_ThreadLoop(); 179} 180 181// _ThreadLoop 182int32 183RequestThread::_ThreadLoop() 184{ 185 tls_set(sTLSVariable, this); 186 if (!fTerminating) { 187 UserlandRequestHandler handler(fFileSystem, false); 188 return fPort->HandleRequests(&handler); 189 } 190 return B_OK; 191} 192 193