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
RequestThreadContext(Volume * volume,KernelRequest * request)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
~RequestThreadContext()40 RequestThreadContext::~RequestThreadContext()
41 {
42 if (fThread)
43 fThread->SetContext(fPreviousContext);
44 }
45
46 // GetThread
47 RequestThread*
GetThread() const48 RequestThreadContext::GetThread() const
49 {
50 return fThread;
51 }
52
53 // GetVolume
54 UserlandFS::Volume*
GetVolume() const55 RequestThreadContext::GetVolume() const
56 {
57 return fVolume;
58 }
59
60
61 // RequestThread
62
63 // constructor
RequestThread()64 RequestThread::RequestThread()
65 : fThread(-1),
66 fFileSystem(NULL),
67 fPort(NULL),
68 fContext(NULL),
69 fTerminating(false)
70 {
71 }
72
73 // destructor
~RequestThread()74 RequestThread::~RequestThread()
75 {
76 PrepareTermination();
77 Terminate();
78 delete fPort;
79 }
80
81 // Init
82 status_t
Init(FileSystem * fileSystem)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
Run()105 RequestThread::Run()
106 {
107 resume_thread(fThread);
108 }
109
110 // PrepareTermination
111 void
PrepareTermination()112 RequestThread::PrepareTermination()
113 {
114 if (fTerminating)
115 return;
116 fTerminating = true;
117 if (fPort)
118 fPort->Close();
119 }
120
121 // Terminate
122 void
Terminate()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*
GetPortInfo() const134 RequestThread::GetPortInfo() const
135 {
136 return (fPort ? fPort->GetPortInfo() : NULL);
137 }
138
139 // GetFileSystem
140 UserlandFS::FileSystem*
GetFileSystem() const141 RequestThread::GetFileSystem() const
142 {
143 return fFileSystem;
144 }
145
146 // GetPort
147 RequestPort*
GetPort() const148 RequestThread::GetPort() const
149 {
150 return fPort;
151 }
152
153 // GetContext
154 RequestThreadContext*
GetContext() const155 RequestThread::GetContext() const
156 {
157 return fContext;
158 }
159
160 // GetCurrentThread
161 RequestThread*
GetCurrentThread()162 RequestThread::GetCurrentThread()
163 {
164 return (RequestThread*)tls_get(sTLSVariable);
165 }
166
167 // SetContext
168 void
SetContext(RequestThreadContext * context)169 RequestThread::SetContext(RequestThreadContext* context)
170 {
171 fContext = context;
172 }
173
174 // _ThreadEntry
175 int32
_ThreadEntry(void * data)176 RequestThread::_ThreadEntry(void* data)
177 {
178 return ((RequestThread*)data)->_ThreadLoop();
179 }
180
181 // _ThreadLoop
182 int32
_ThreadLoop()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