The Pedigree Project  0.1
PosixSubsystem.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 POSIX_SUBSYSTEM_H
21 #define POSIX_SUBSYSTEM_H
22 
23 #include "pedigree/kernel/Subsystem.h"
24 #include "pedigree/kernel/compiler.h"
25 #include "pedigree/kernel/process/Mutex.h"
26 #include "pedigree/kernel/process/Semaphore.h"
27 #include "pedigree/kernel/process/SignalEvent.h"
28 #include "pedigree/kernel/processor/types.h"
29 
30 #include "pedigree/kernel/LockGuard.h"
31 #include "pedigree/kernel/utilities/ExtensibleBitmap.h"
32 #include "pedigree/kernel/utilities/LruCache.h"
34 #include "pedigree/kernel/utilities/Tree.h"
36 #include "pedigree/kernel/utilities/Vector.h"
37 
38 #include "modules/subsys/posix/logging.h"
39 
40 class File;
41 class Filesystem;
42 class UnixSocket;
43 class LockedFile;
44 class FileDescriptor;
45 class PosixSubsystem;
46 
47 extern PosixSubsystem *getSubsystem();
48 extern FileDescriptor *getDescriptor(int fd);
49 extern void addDescriptor(int fd, FileDescriptor *f);
50 extern size_t getAvailableDescriptor();
51 
52 // Grabs a subsystem for use.
53 #define GRAB_POSIX_SUBSYSTEM(returnValue) \
54  PosixSubsystem *pSubsystem = getSubsystem(); \
55  if (!pSubsystem) \
56  { \
57  return (returnValue); \
58  }
59 #define GRAB_POSIX_SUBSYSTEM_NORET \
60  PosixSubsystem *pSubsystem = getSubsystem(); \
61  if (!pSubsystem) \
62  { \
63  return; \
64  }
65 
67 extern RadixTree<LockedFile *> g_PosixGlobalLockedFiles;
69 
74 {
75  public:
77  virtual ~ProcessGroupManager();
78 
79  static ProcessGroupManager &instance()
80  {
81  return m_Instance;
82  }
83 
85  size_t allocateGroupId();
86 
88  void setGroupId(size_t gid);
89 
91  bool isGroupIdValid(size_t gid) const;
92 
94  void returnGroupId(size_t gid);
95 
96  private:
97  static ProcessGroupManager m_Instance;
102 };
103 
106 {
107  public:
109  static const size_t SafeRegion = 0x0; // Region check is always done.
110  static const size_t SafeRead = 0x1;
111  static const size_t SafeWrite = 0x2;
112 
114  enum Abi
115  {
116  PosixAbi = 0,
117  LinuxAbi = 1,
118  };
119 
122  : Subsystem(Posix), m_SignalHandlers(), m_SignalHandlersLock(),
123  m_FdMap(), m_NextFd(0), m_FdLock(), m_FdBitmap(), m_LastFd(0),
124  m_FreeCount(1), m_AltSigStack(), m_SyncObjects(), m_Threads(),
125  m_ThreadWaiters(), m_NextThreadWaiter(0), m_Abi(PosixAbi),
126  m_bAcquired(false), m_pAcquiredThread(nullptr)
127  {
128  }
129 
132 
135  : Subsystem(type), m_SignalHandlers(), m_SignalHandlersLock(),
136  m_FdMap(), m_NextFd(0), m_FdLock(), m_FdBitmap(), m_LastFd(0),
137  m_FreeCount(1), m_AltSigStack(), m_SyncObjects(), m_Threads(),
138  m_ThreadWaiters(), m_NextThreadWaiter(0), m_Abi(PosixAbi),
139  m_bAcquired(false), m_pAcquiredThread(nullptr)
140  {
141  }
142 
144  virtual ~PosixSubsystem();
145 
146  /* Acquire mutual exclusion on the PosixSubsystem. */
147  virtual void acquire();
148 
150  virtual void release();
151 
166  static bool checkAddress(uintptr_t addr, size_t extent, size_t flags);
167 
169  virtual bool kill(KillReason killReason, Thread *pThread);
170 
172  virtual void threadException(Thread *pThread, ExceptionType eType);
173 
175  virtual void sendSignal(Thread *pThread, int signal, bool yield = true);
176 
178  struct AlternateSignalStack
183  {
185  AlternateSignalStack() : base(0), size(0), inUse(false), enabled(false)
186  {
187  }
188 
190  uintptr_t base;
191 
193  size_t size;
194 
196  bool inUse;
197 
199  bool enabled;
200  };
201 
204  {
205  return m_AltSigStack;
206  }
207 
210  {
211  m_AltSigStack = s;
212  }
213 
216  {
217  SignalHandler() : sig(255), pEvent(0), sigMask(), flags(0), type(0)
218  {
219  }
220 
221  SignalHandler(const SignalHandler &s)
222  : sig(s.sig), pEvent(new SignalEvent(*(s.pEvent))),
223  sigMask(s.sigMask), flags(s.flags), type(s.type)
224  {
225  }
226 
227  ~SignalHandler()
228  {
229  if (pEvent)
230  {
231  pEvent->waitForDeliveries();
232  delete pEvent;
233  }
234  }
235 
236  SignalHandler &operator=(const SignalHandler &s)
237  {
238  if (this == &s)
239  {
240  return *this;
241  }
242 
243  if (pEvent)
244  {
245  delete pEvent;
246  }
247 
248  sig = s.sig;
249  pEvent = new SignalEvent(*(s.pEvent));
250  sigMask = s.sigMask;
251  flags = s.flags;
252  type = s.type;
253  return *this;
254  }
255 
257  size_t sig;
258 
261 
263  uint32_t sigMask;
264 
266  uint32_t flags;
267 
269  int type;
270  };
271 
273  void setSignalHandler(size_t sig, SignalHandler *handler);
274 
277  {
278  while (!m_SignalHandlersLock.enter())
279  ;
280  SignalHandler *ret = m_SignalHandlers.lookup(sig % 32);
281  m_SignalHandlersLock.leave();
282  return ret;
283  }
284 
285  void exit(int code) NORETURN;
286 
288  bool copyDescriptors(PosixSubsystem *pSubsystem);
289 
291  size_t getFd();
292 
294  void allocateFd(size_t fdNum);
295 
298  void freeFd(size_t fdNum);
299 
301  void freeMultipleFds(
302  bool bOnlyCloExec = false, size_t iFirst = 0, size_t iLast = -1);
303 
305  FileDescriptor *getFileDescriptor(size_t fd);
306 
308  void addFileDescriptor(size_t fd, FileDescriptor *pFd);
309 
316  {
317  public:
318  PosixSyncObject() : pObject(0), isMutex(false)
319  {
320  }
321  ~PosixSyncObject()
322  {
323  }
324 
325  void *pObject;
326  bool isMutex;
327 
328  private:
330  const PosixSyncObject &operator=(const PosixSyncObject &);
331  };
332 
335  {
336  return m_SyncObjects.lookup(n);
337  }
338 
340  void insertSyncObject(size_t n, PosixSyncObject *sem)
341  {
342  PosixSyncObject *t = m_SyncObjects.lookup(n);
343  if (t)
344  {
345  m_SyncObjects.remove(n);
346  delete t;
347  }
348 
349  m_SyncObjects.insert(n, sem);
350  }
351 
353  void removeSyncObject(size_t n)
354  {
355  PosixSyncObject *t = m_SyncObjects.lookup(n);
356  if (t)
357  {
358  m_SyncObjects.remove(n);
359  delete t;
360  }
361  }
362 
365  {
367  void (*destructor)(void *);
368 
370  void *buffer;
371  };
372 
375  {
376  public:
377  PosixThread()
378  : pThread(0), isRunning(true), returnValue(0), canReclaim(false),
379  isDetached(false), m_ThreadData(), m_ThreadKeys(), lastDataKey(0),
380  nextDataKey(0)
381  {
382  }
383  ~PosixThread()
384  {
385  }
386 
387  Thread *pThread;
388  Mutex isRunning;
389  void *returnValue;
390 
391  bool canReclaim;
392  bool isDetached;
393 
398  ExtensibleBitmap m_ThreadKeys;
399 
402  {
403  return m_ThreadData.lookup(key);
404  }
405 
410  void removeThreadData(size_t key)
411  {
412  m_ThreadData.remove(key);
413  }
414 
419  bool addThreadData(size_t key, PosixThreadKey *info)
420  {
421  if (m_ThreadData.lookup(key))
422  return false;
423  m_ThreadData.insert(key, info);
424  return true;
425  }
426 
428  size_t lastDataKey;
429 
431  size_t nextDataKey;
432 
433  private:
434  PosixThread(const PosixThread &);
435  const PosixThread &operator=(const PosixThread &);
436  };
437 
440  {
441  return m_Threads.lookup(n);
442  }
443 
445  void insertThread(size_t n, PosixThread *thread)
446  {
447  PosixThread *t = m_Threads.lookup(n);
448  if (t)
449  m_Threads.remove(n);
450  return m_Threads.insert(n, thread);
452  }
453 
455  void removeThread(size_t n)
456  {
457  m_Threads.remove(
458  n);
459  }
460 
463  {
464  return m_ThreadWaiters.lookup(n);
465  }
466 
469  {
470  void *descriptor = reinterpret_cast<void *>(m_NextThreadWaiter++);
471  Semaphore *t = m_ThreadWaiters.lookup(descriptor);
472  if (t)
473  m_ThreadWaiters.remove(descriptor);
474  m_ThreadWaiters.insert(descriptor, waiter);
475  return descriptor;
476  }
477 
479  void removeThreadWaiter(void *n)
480  {
481  m_ThreadWaiters.remove(n);
482  }
483 
484  bool checkAccess(
485  FileDescriptor *pFileDescriptor, bool bRead, bool bWrite,
486  bool bExecute) const;
487 
489  virtual bool
490  invoke(const char *name, Vector<String> &argv, Vector<String> &env);
491 
493  virtual bool invoke(
494  const char *name, Vector<String> &argv, Vector<String> &env,
495  SyscallState &state);
496 
498  virtual bool invoke(
499  File *originalFile, const String &originalName, Vector<String> &argv,
500  Vector<String> &env);
501 
503  virtual bool invoke(
504  File *originalFile, const String &originalName, Vector<String> &argv,
505  Vector<String> &env, SyscallState &state);
506 
507  virtual File *findFile(const String &path, File *workingDir);
508 
510  Abi getAbi() const
511  {
512  return m_Abi;
513  }
514 
516  void setAbi(Abi which)
517  {
518  m_Abi = which;
519  }
520 
521  private:
522  virtual void threadRemoved(Thread *pThread);
523 
525  bool loadElf(
526  File *pFile, uintptr_t mappedAddress, uintptr_t &newAddress,
527  uintptr_t &finalAddress, bool &relocated);
528 
529  bool invoke(
530  const char *name, Vector<String> &argv, Vector<String> &env,
531  SyscallState *state);
532 
534  bool invoke(
535  File *originalFile, const String &originalName, Vector<String> &argv,
536  Vector<String> &env, SyscallState *state);
537 
539  bool parseShebang(File *pFile, File *&outFile, Vector<String> &argv);
540 
543 
546 
555  size_t m_NextFd;
567  size_t m_LastFd;
589  size_t m_NextThreadWaiter;
590 
596 
601 
606 
611 
619 
621  Filesystem *m_pRootFs = nullptr;
622 };
623 
624 #endif
Tree< size_t, PosixThreadKey * > m_ThreadData
Abi getAbi() const
A key/value dictionary for string keys.
Definition: RadixTree.h:45
Thread * m_pAcquiredThread
A vector / dynamic array.
ExtensibleBitmap m_GroupIds
Tree< size_t, FileDescriptor * > m_FdMap
void removeThreadWaiter(void *n)
void * insertThreadWaiter(Semaphore *waiter)
ExtensibleBitmap m_FdBitmap
size_t size
Size of the stack.
Definition: Mutex.h:58
Tree< size_t, PosixThread * > m_Threads
Tree< void *, Semaphore * > m_ThreadWaiters
Definition: String.h:49
void setGroupId(size_t gid)
Tree< size_t, SignalHandler * > m_SignalHandlers
Tree< size_t, PosixSyncObject * > m_SyncObjects
PosixSyncObject * getSyncObject(size_t n)
void removeThreadData(size_t key)
AlternateSignalStack m_AltSigStack
void * buffer
Buffer pointer.
void setAlternateSignalStack(AlternateSignalStack &s)
PosixThreadKey * getThreadData(size_t key)
uint32_t flags
Signal handler flags.
void insert(const K &key, const E &value)
Definition: Tree.h:173
SignalHandler * getSignalHandler(size_t sig)
PosixSubsystem(SubsystemType type)
LruCache< String, File * > m_FindFileCache
LRU cache for file lookups. Many usage patterns involve something like a stat() immediately followed ...
void removeThread(size_t n)
bool addThreadData(size_t key, PosixThreadKey *info)
void insertSyncObject(size_t n, PosixSyncObject *sem)
int type
Type - 0 = normal, 1 = SIG_DFL, 2 = SIG_IGN.
SignalEvent * pEvent
Event for the signal handler.
A key/value dictionary.
Definition: Tree.h:33
void removeSyncObject(size_t n)
size_t sig
Signal number.
uintptr_t base
The location of this stack.
bool inUse
Are we to use this alternate stack rather than a normal stack?
PosixThread * getThread(size_t n)
Definition: Thread.h:54
UnlikelyLock m_SignalHandlersLock
void setAbi(Abi which)
void returnGroupId(size_t gid)
Semaphore * getThreadWaiter(void *n)
size_t lastDataKey
Last data key that was allocated (for the bitmap)
void remove(const K &key)
Definition: Tree.h:242
void insertThread(size_t n, PosixThread *thread)
size_t nextDataKey
Next data key available.
AlternateSignalStack()
Default constructor.
uint32_t sigMask
Signal mask to set when this signal handler is called.
Definition: File.h:66
UnlikelyLock m_FdLock
E lookup(const K &key) const
Definition: Tree.h:192
bool isGroupIdValid(size_t gid) const
AlternateSignalStack & getAlternateSignalStack()
Implements a Radix Tree, a kind of Trie with compressed keys.