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