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