The Pedigree Project  0.1
Thread.h
1 /*
2  * Copyright (c) 2008-2014, Pedigree Developers
3  *
4  * Please see the CONTRIB file in the root of the source tree for a full
5  * list of contributors.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #ifndef THREAD_H
21 #define THREAD_H
22 
23 #ifdef THREADS
24 
25 #include "pedigree/kernel/Spinlock.h"
26 #include "pedigree/kernel/compiler.h"
27 #include "pedigree/kernel/process/Event.h"
28 #include "pedigree/kernel/process/SchedulingAlgorithm.h"
29 #include "pedigree/kernel/processor/ProcessorInformation.h"
30 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
31 #include "pedigree/kernel/processor/state_forward.h"
32 #include "pedigree/kernel/processor/types.h"
33 #include "pedigree/kernel/utilities/List.h"
34 #include "pedigree/kernel/utilities/RequestQueue.h"
35 #include "pedigree/kernel/utilities/SharedPointer.h"
36 #include "pedigree/kernel/utilities/new"
37 
38 class ExtensibleBitmap;
39 class Process;
40 
42 #define THREAD_TLS_SIZE 0x1000
43 
55 {
56  friend class PerProcessorScheduler;
57  // To set uninterruptible state.
58  friend class Uninterruptible;
59 
60  public:
62  enum Status
63  {
64  Ready,
65  Running,
66  Sleeping,
67  Zombie,
68  AwaitingJoin,
69  Suspended,
70  };
71 
74  {
75  None,
76  SemWait,
77  CondWait,
78  Joining
79  };
80 
83  {
84  NotWoken, // can be used to check if a reason has been set yet
85  WokenByAlarm,
86  WokenByEvent,
87  WokenBecauseTerminating,
88  WokenBecauseUnwinding,
89  Unknown
90  };
91 
93  typedef int (*ThreadStartFunc)(void *);
94 
113  Thread(
114  Process *pParent, ThreadStartFunc pStartFunction, void *pParam,
115  void *pStack = 0, bool semiUser = false, bool bDontPickCore = false,
116  bool delayedStart = false);
117 
120  Thread(Process *pParent);
121 
125  Thread(Process *pParent, SyscallState &state, bool delayedStart = false);
126 
131  virtual ~Thread();
132 
139  void shutdown();
140 
141  /* Forces the thread to run on the bootstrap processor. */
142  void forceToStartupProcessor();
143 
146  SchedulerState &state();
147 
153  SchedulerState &pushState();
154 
159  void popState(bool clean = true);
160 
161  VirtualAddressSpace::Stack *getStateUserStack();
162 
163  void setStateUserStack(VirtualAddressSpace::Stack *st);
164 
166  size_t getStateLevel() const;
167 
169  void allocateStackAtLevel(size_t stateLevel);
170 
172  void setKernelStack();
173 
178  void pokeState(size_t stateLevel, SchedulerState &state);
179 
182  {
183  return m_pParent;
184  }
185 
186  void setParent(Process *p)
187  {
188  m_pParent = p;
189  }
190 
193  {
194  return m_Status;
195  }
196 
198  void setStatus(Status s);
199 
202  {
203  return m_ExitCode;
204  }
205 
207  void *getKernelStack();
208 
210  size_t getId()
211  {
212  return m_Id;
213  }
214 
216  size_t getErrno()
217  {
218  return m_Errno;
219  }
220 
222  void setErrno(size_t err)
223  {
224  m_Errno = err;
225  }
226 
230  {
231  return m_bInterrupted;
232  }
233 
235  void setInterrupted(bool b)
236  {
237  m_bInterrupted = b;
238  }
239 
242  {
243  Continue = 0,
245  Exit
246  };
247 
262  {
263  return m_UnwindState;
264  }
267  {
268  m_UnwindState = ut;
269 
270  if (ut != Continue)
271  {
272  reportWakeup(WokenBecauseUnwinding);
273  }
274  }
275 
276  void setBlockingThread(Thread *pT)
277  {
278  m_StateLevels[getStateLevel()].m_pBlockingThread = pT;
279  }
280  Thread *getBlockingThread(size_t level = ~0UL)
281  {
282  if (level == ~0UL)
283  level = getStateLevel();
284  return m_StateLevels[level].m_pBlockingThread;
285  }
286 
288  DebugState getDebugState(uintptr_t &address)
289  {
290  address = m_DebugStateAddress;
291  return m_DebugState;
292  }
294  void setDebugState(DebugState state, uintptr_t address)
295  {
296  m_DebugState = state;
297  m_DebugStateAddress = address;
298  }
299 
302  {
303  return m_Lock;
304  }
305 
310  bool sendEvent(Event *pEvent);
311 
315  void inhibitEvent(size_t eventNumber, bool bInhibit);
316 
318  void cullEvent(Event *pEvent);
319 
322  void cullEvent(size_t eventNumber);
323 
328  Event *getNextEvent();
329 
330  bool hasEvents();
331 
333  bool hasEvent(Event *pEvent);
334  bool hasEvent(size_t eventNumber);
335 
336  void setPriority(size_t p)
337  {
338  m_Priority = p;
339  }
340  size_t getPriority()
341  {
342  return m_Priority;
343  }
344 
346  void addRequest(RequestQueue::Request *req);
347 
349  void removeRequest(RequestQueue::Request *req);
350 
352  void unexpectedExit();
353 
355  uintptr_t getTlsBase();
356 
362  void resetTlsBase();
363 
369  void setTlsBase(uintptr_t base);
370 
372  inline
373 #ifdef MULTIPROCESSOR
375 #else
376  size_t
377 #endif
379  {
380  return m_ProcId;
381  }
382 
384  inline void setCpuId(
385 #ifdef MULTIPROCESSOR
387 #else
388  size_t
389 #endif
390  id)
391  {
392  m_ProcId = id;
393  }
394 
402  bool join();
403 
412  bool detach();
413 
417  bool detached() const
418  {
419  return m_bDetached;
420  }
421 
428  static void threadExited() NORETURN;
429 
431  bool isInterruptible();
432 
437  void addWakeupWatcher(WakeReason *watcher);
438 
440  void removeWakeupWatcher(WakeReason *watcher);
441 
443  class PerProcessorScheduler *getScheduler() const;
444 
445  protected:
447  void setScheduler(class PerProcessorScheduler *pScheduler);
448 
450  void setInterruptible(bool state);
451 
452  private:
454  Thread(const Thread &);
456  Thread &operator=(const Thread &);
457 
459  void cleanStateLevel(size_t level);
460 
462  void reportWakeup(WakeReason reason);
463  void reportWakeupUnlocked(WakeReason reason);
464 
466  struct StateLevel
467  {
468  StateLevel();
469  ~StateLevel();
470 
471  StateLevel(const StateLevel &s);
472  StateLevel &operator=(const StateLevel &s);
473 
475  SchedulerState *m_State;
476 
479 
480  VirtualAddressSpace::Stack *m_pUserStack;
481 
487 
494 
495  Thread *m_pBlockingThread;
496  };
497 
499  size_t m_nStateLevel = 0;
500 
502  Process *m_pParent = nullptr;
503 
507  void *m_pAllocatedStack = nullptr;
508 
510  size_t m_Id = 0;
511 
513  size_t m_Errno = 0;
514 
516  uintptr_t m_DebugStateAddress = 0;
517 
518  class PerProcessorScheduler *m_pScheduler = nullptr;
519 
521  size_t m_Priority = DEFAULT_PRIORITY;
522 
524  void *m_pTlsBase = nullptr;
525 
526 #ifdef MULTIPROCESSOR
528 #else
529  size_t
530 #endif
531  m_ProcId = 0;
532 
534  Thread *m_pWaiter = nullptr;
535 
538 
541 
544 
547 
550 
551  StateLevel m_StateLevels[MAX_NESTED_EVENTS];
552 
554  volatile Status m_Status = Ready;
555 
557  int m_ExitCode = 0;
558 
561  DebugState m_DebugState = None;
562 
563  UnwindType m_UnwindState = Continue;
564 
567  bool m_bInterrupted = false;
568 
570  bool m_bTlsBaseOverride = false;
571 
574  bool m_bRemovingRequests = false;
575 
577  bool m_bDetached = false;
578 
580  bool m_bInterruptible = true;
581 };
582 
583 #endif
584 
585 #endif
bool wasInterrupted()
Definition: Thread.h:229
SharedPointer< ExtensibleBitmap > m_InhibitMask
Definition: Thread.h:493
UnwindType
Definition: Thread.h:241
List< RequestQueue::Request * > m_PendingRequests
Definition: Thread.h:546
Spinlock m_Lock
Definition: Thread.h:537
void setDebugState(DebugState state, uintptr_t address)
Definition: Thread.h:294
List< Event * > m_EventQueue
Definition: Thread.h:543
WakeReason
Definition: Thread.h:82
void setUnwindState(UnwindType ut)
Definition: Thread.h:266
Spinlock m_ConcurrencyLock
Definition: Thread.h:540
VirtualAddressSpace::Stack * m_pKernelStack
Definition: Thread.h:478
void setErrno(size_t err)
Definition: Thread.h:222
DebugState
Definition: Thread.h:73
VirtualAddressSpace::Stack * m_pAuxillaryStack
Definition: Thread.h:486
Status
Definition: Thread.h:62
Spinlock & getLock()
Definition: Thread.h:301
PerProcessorScheduler & operator=(const PerProcessorScheduler &)
size_t ProcessorId
Status getStatus() const
Definition: Thread.h:192
SchedulerState * m_State
Definition: Thread.h:475
Process * getParent() const
Definition: Thread.h:181
Definition: Thread.h:54
Definition: Event.h:48
void setInterrupted(bool b)
Definition: Thread.h:235
size_t getId()
Definition: Thread.h:210
int getExitCode()
Definition: Thread.h:201
List< WakeReason * > m_WakeWatchers
Definition: Thread.h:549
size_t getErrno()
Definition: Thread.h:216
UnwindType getUnwindState()
Definition: Thread.h:261
size_t getCpuId()
Definition: Thread.h:378
void setCpuId(size_t id)
Definition: Thread.h:384
DebugState getDebugState(uintptr_t &address)
Definition: Thread.h:288
bool detached() const
Definition: Thread.h:417