xref: /haiku/src/add-ons/kernel/file_systems/userlandfs/server/RequestThread.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
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