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 18 static const int32 sTLSVariable = tls_allocate(); 19 20 21 // constructor 22 RequestThreadContext::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 40 RequestThreadContext::~RequestThreadContext() 41 { 42 if (fThread) 43 fThread->SetContext(fPreviousContext); 44 } 45 46 // GetThread 47 RequestThread* 48 RequestThreadContext::GetThread() const 49 { 50 return fThread; 51 } 52 53 // GetVolume 54 UserlandFS::Volume* 55 RequestThreadContext::GetVolume() const 56 { 57 return fVolume; 58 } 59 60 61 // RequestThread 62 63 // constructor 64 RequestThread::RequestThread() 65 : fThread(-1), 66 fFileSystem(NULL), 67 fPort(NULL), 68 fContext(NULL), 69 fTerminating(false) 70 { 71 } 72 73 // destructor 74 RequestThread::~RequestThread() 75 { 76 PrepareTermination(); 77 Terminate(); 78 delete fPort; 79 } 80 81 // Init 82 status_t 83 RequestThread::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 104 void 105 RequestThread::Run() 106 { 107 resume_thread(fThread); 108 } 109 110 // PrepareTermination 111 void 112 RequestThread::PrepareTermination() 113 { 114 if (fTerminating) 115 return; 116 fTerminating = true; 117 if (fPort) 118 fPort->Close(); 119 } 120 121 // Terminate 122 void 123 RequestThread::Terminate() 124 { 125 if (fThread >= 0) { 126 int32 result; 127 wait_for_thread(fThread, &result); 128 fThread = -1; 129 } 130 } 131 132 // GetPortInfo 133 const Port::Info* 134 RequestThread::GetPortInfo() const 135 { 136 return (fPort ? fPort->GetPortInfo() : NULL); 137 } 138 139 // GetFileSystem 140 UserlandFS::FileSystem* 141 RequestThread::GetFileSystem() const 142 { 143 return fFileSystem; 144 } 145 146 // GetPort 147 RequestPort* 148 RequestThread::GetPort() const 149 { 150 return fPort; 151 } 152 153 // GetContext 154 RequestThreadContext* 155 RequestThread::GetContext() const 156 { 157 return fContext; 158 } 159 160 // GetCurrentThread 161 RequestThread* 162 RequestThread::GetCurrentThread() 163 { 164 return (RequestThread*)tls_get(sTLSVariable); 165 } 166 167 // SetContext 168 void 169 RequestThread::SetContext(RequestThreadContext* context) 170 { 171 fContext = context; 172 } 173 174 // _ThreadEntry 175 int32 176 RequestThread::_ThreadEntry(void* data) 177 { 178 return ((RequestThread*)data)->_ThreadLoop(); 179 } 180 181 // _ThreadLoop 182 int32 183 RequestThread::_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