summaryrefslogtreecommitdiffhomepage
path: root/frameworks/libThread.fwrk/src/ThreadMgr.cpp
blob: 6a7843f2ac6bb63a7fe54872f92df33936c78d7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// SPDX-License-Identifier: Apache-2.0
// Copyright 2026, Amlal El Mahrouss (amlal@nekernel.org)
// Licensed under the Apache License, Version 2.0 (see LICENSE file)
// Official repository: https://github.com/ne-foss-org/ne_system

#include <libSystem/SystemKit/Err.h>
#include <libThread.fwrk/headers/Config.h>

#define kThreadMapMax (1024UL)
#define kThreadBaseHash (0x5555ffff6ULL)

/// @brief The registered thread for a specific process.
static ThreadRef kThreadMap[kThreadMapMax];

/// @brief Exit codes as we want to track them.
static SInt32 kThreadExitCodes[kThreadMapMax];

/// @brief This hash-list stores the thread to be run.
static ThreadRef kThreadHeads[kThreadMapMax];

static ThreadRef kCurrentThread;

static __THREAD_UNSAFE Void _ThrRunThread(SInt32 argument_count, VoidPtr args,
                                          ThrProcKind procedure, ThreadRef ref) {
  static SemaphoreRef sem_ref = SemCreate(0, 1000, "ThreadSem");

  if (sem_ref) return;

  auto ret                                      = procedure(argument_count, (Char**) args);
  kThreadExitCodes[kThreadMapMax % ref->__hash] = ret;

  if (ref == kCurrentThread) kCurrentThread = nullptr;

  SemClose(sem_ref);
  sem_ref = nullptr;
}

IMPORT_C ThreadRef ThrCreateThread(const Char* thread_name, ThrProcKind procedure,
                                   SInt32 argument_count, VoidPtr args, SInt32 flags) {
  ThreadRef ref = new REF_TYPE;
  if (!ref) return nullptr;

  if (!thread_name || !procedure) {
    delete ref;
    ref = nullptr;
    return nullptr;
  }

  ref->__hash = *(UInt32*) thread_name;
  ref->__hash += kThreadBaseHash;  // pad hash with a seed.

  ref->__self = (VoidPtr) procedure;

  kThreadMap[kThreadMapMax % ref->__hash]   = ref;
  kThreadHeads[kThreadMapMax % ref->__hash] = ref;

  kCurrentThread = ref;

  _ThrRunThread(argument_count, args, procedure, ref);

  return ref;
}

IMPORT_C SInt32 ThrExitThread(_Input ThreadRef ref, _Input SInt32 exit_code) {
  if (!ref) return kErrorInvalidData;

  kThreadMap[kThreadMapMax % ref->__hash]   = nullptr;
  kThreadHeads[kThreadMapMax % ref->__hash] = nullptr;

  if (kCurrentThread == ref) kCurrentThread = nullptr;

  kThreadExitCodes[kThreadMapMax % ref->__hash] = exit_code;
  return kErrorSuccess;
}