Task.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798
  1. #include "types.h"
  2. #include "Task.h"
  3. #include "kmalloc.h"
  4. #include "VGA.h"
  5. #include "StdLib.h"
  6. #include "i386.h"
  7. #include "system.h"
  8. #include <VirtualFileSystem/FileHandle.h>
  9. #include <VirtualFileSystem/VirtualFileSystem.h>
  10. #include <ELFLoader/ExecSpace.h>
  11. #include "MemoryManager.h"
  12. #include "errno.h"
  13. //#define DEBUG_IO
  14. //#define TASK_DEBUG
  15. static const DWORD defaultStackSize = 16384;
  16. Task* current;
  17. Task* s_kernelTask;
  18. static pid_t next_pid;
  19. static InlineLinkedList<Task>* s_tasks;
  20. static InlineLinkedList<Task>* s_deadTasks;
  21. static bool contextSwitch(Task*);
  22. static void redoKernelTaskTSS()
  23. {
  24. if (!s_kernelTask->selector())
  25. s_kernelTask->setSelector(allocateGDTEntry());
  26. auto& tssDescriptor = getGDTEntry(s_kernelTask->selector());
  27. tssDescriptor.setBase(&s_kernelTask->tss());
  28. tssDescriptor.setLimit(0xffff);
  29. tssDescriptor.dpl = 0;
  30. tssDescriptor.segment_present = 1;
  31. tssDescriptor.granularity = 1;
  32. tssDescriptor.zero = 0;
  33. tssDescriptor.operation_size = 1;
  34. tssDescriptor.descriptor_type = 0;
  35. tssDescriptor.type = 9;
  36. flushGDT();
  37. }
  38. void Task::prepForIRETToNewTask()
  39. {
  40. redoKernelTaskTSS();
  41. s_kernelTask->tss().backlink = current->selector();
  42. loadTaskRegister(s_kernelTask->selector());
  43. }
  44. void Task::initialize()
  45. {
  46. current = nullptr;
  47. next_pid = 0;
  48. s_tasks = new InlineLinkedList<Task>;
  49. s_deadTasks = new InlineLinkedList<Task>;
  50. s_kernelTask = Task::createKernelTask(nullptr, "colonel");
  51. redoKernelTaskTSS();
  52. loadTaskRegister(s_kernelTask->selector());
  53. }
  54. #ifdef TASK_SANITY_CHECKS
  55. void Task::checkSanity(const char* msg)
  56. {
  57. char ch = current->name()[0];
  58. kprintf("<%p> %s{%u}%b [%d] :%b: sanity check <%s>\n",
  59. current->name().characters(),
  60. current->name().characters(),
  61. current->name().length(),
  62. current->name()[current->name().length() - 1],
  63. current->pid(), ch, msg ? msg : "");
  64. ASSERT((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
  65. }
  66. #endif
  67. void Task::allocateLDT()
  68. {
  69. ASSERT(!m_tss.ldt);
  70. static const WORD numLDTEntries = 4;
  71. WORD newLDTSelector = allocateGDTEntry();
  72. m_ldtEntries = new Descriptor[numLDTEntries];
  73. #if 0
  74. kprintf("new ldt selector = %x\n", newLDTSelector);
  75. kprintf("new ldt table at = %p\n", m_ldtEntries);
  76. kprintf("new ldt table size = %u\n", (numLDTEntries * 8) - 1);
  77. #endif
  78. Descriptor& ldt = getGDTEntry(newLDTSelector);
  79. ldt.setBase(m_ldtEntries);
  80. ldt.setLimit(numLDTEntries * 8 - 1);
  81. ldt.dpl = 0;
  82. ldt.segment_present = 1;
  83. ldt.granularity = 0;
  84. ldt.zero = 0;
  85. ldt.operation_size = 1;
  86. ldt.descriptor_type = 0;
  87. ldt.type = Descriptor::LDT;
  88. m_tss.ldt = newLDTSelector;
  89. }
  90. Vector<Task*> Task::allTasks()
  91. {
  92. InterruptDisabler disabler;
  93. Vector<Task*> tasks;
  94. tasks.ensureCapacity(s_tasks->sizeSlow());
  95. for (auto* task = s_tasks->head(); task; task = task->next())
  96. tasks.append(task);
  97. return tasks;
  98. }
  99. Task::Region* Task::allocateRegion(size_t size, String&& name)
  100. {
  101. // FIXME: This needs sanity checks. What if this overlaps existing regions?
  102. auto zone = MemoryManager::the().createZone(size);
  103. ASSERT(zone);
  104. m_regions.append(make<Region>(m_nextRegion, size, move(zone), move(name)));
  105. m_nextRegion = m_nextRegion.offset(size).offset(16384);
  106. return m_regions.last().ptr();
  107. }
  108. bool Task::deallocateRegion(Region& region)
  109. {
  110. for (size_t i = 0; i < m_regions.size(); ++i) {
  111. if (m_regions[i].ptr() == &region) {
  112. // FIXME: This seems racy.
  113. MemoryManager::the().unmapRegion(*this, region);
  114. m_regions.remove(i);
  115. return true;
  116. }
  117. }
  118. return false;
  119. }
  120. Task::Region* Task::regionFromRange(LinearAddress laddr, size_t size)
  121. {
  122. for (auto& region : m_regions) {
  123. if (region->linearAddress == laddr && region->size == size)
  124. return region.ptr();
  125. }
  126. return nullptr;
  127. }
  128. void* Task::sys$mmap(void* addr, size_t size)
  129. {
  130. // FIXME: Implement mapping at a client-preferred address.
  131. ASSERT(addr == nullptr);
  132. auto* region = allocateRegion(size, "mmap");
  133. if (!region)
  134. return (void*)-1;
  135. MemoryManager::the().mapRegion(*this, *region);
  136. return (void*)region->linearAddress.get();
  137. }
  138. int Task::sys$munmap(void* addr, size_t size)
  139. {
  140. auto* region = regionFromRange(LinearAddress((dword)addr), size);
  141. if (!region)
  142. return -1;
  143. if (!deallocateRegion(*region))
  144. return -1;
  145. return 0;
  146. }
  147. int Task::sys$spawn(const char* path)
  148. {
  149. int error = 0;
  150. auto* child = Task::createUserTask(path, m_uid, m_gid, m_pid, error);
  151. if (child)
  152. return child->pid();
  153. return error;
  154. }
  155. Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t parentPID, int& error)
  156. {
  157. auto parts = path.split('/');
  158. if (parts.isEmpty()) {
  159. error = -ENOENT;
  160. return nullptr;
  161. }
  162. auto handle = VirtualFileSystem::the().open(path);
  163. if (!handle) {
  164. error = -ENOENT; // FIXME: Get a more detailed error from VFS.
  165. return nullptr;
  166. }
  167. auto elfData = handle->readEntireFile();
  168. if (!elfData) {
  169. error = -EIO; // FIXME: Get a more detailed error from VFS.
  170. return nullptr;
  171. }
  172. InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
  173. Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3);
  174. ExecSpace space;
  175. space.hookableAlloc = [&] (const String& name, size_t size) {
  176. if (!size)
  177. return (void*)nullptr;
  178. size = ((size / 4096) + 1) * 4096;
  179. Region* region = t->allocateRegion(size, String(name));
  180. ASSERT(region);
  181. MemoryManager::the().mapRegion(*t, *region);
  182. return (void*)region->linearAddress.asPtr();
  183. };
  184. bool success = space.loadELF(move(elfData));
  185. if (!success) {
  186. delete t;
  187. kprintf("Failure loading ELF %s\n", path.characters());
  188. error = -ENOEXEC;
  189. return nullptr;
  190. }
  191. t->m_tss.eip = (dword)space.symbolPtr("_start");
  192. if (!t->m_tss.eip) {
  193. delete t;
  194. error = -ENOEXEC;
  195. return nullptr;
  196. }
  197. MemoryManager::the().unmapRegionsForTask(*t);
  198. MemoryManager::the().mapRegionsForTask(*current);
  199. s_tasks->prepend(t);
  200. system.nprocess++;
  201. #ifdef TASK_DEBUG
  202. kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
  203. #endif
  204. error = 0;
  205. return t;
  206. }
  207. Task* Task::createKernelTask(void (*e)(), String&& name)
  208. {
  209. Task* task = new Task(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);
  210. task->m_tss.eip = (dword)e;
  211. if (task->pid() != 0) {
  212. InterruptDisabler disabler;
  213. s_tasks->prepend(task);
  214. system.nprocess++;
  215. #ifdef TASK_DEBUG
  216. kprintf("Kernel task %u (%s) spawned @ %p\n", task->pid(), task->name().characters(), task->m_tss.eip);
  217. #endif
  218. }
  219. return task;
  220. }
  221. Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring)
  222. : m_name(move(name))
  223. , m_pid(next_pid++)
  224. , m_uid(uid)
  225. , m_gid(gid)
  226. , m_state(Runnable)
  227. , m_ring(ring)
  228. , m_parentPID(parentPID)
  229. {
  230. m_fileHandles.append(nullptr); // stdin
  231. m_fileHandles.append(nullptr); // stdout
  232. m_fileHandles.append(nullptr); // stderr
  233. auto* parentTask = Task::fromPID(parentPID);
  234. if (parentTask)
  235. m_cwd = parentTask->m_cwd;
  236. else
  237. m_cwd = "/";
  238. m_nextRegion = LinearAddress(0x600000);
  239. memset(&m_tss, 0, sizeof(m_tss));
  240. if (isRing3()) {
  241. memset(&m_ldtEntries, 0, sizeof(m_ldtEntries));
  242. allocateLDT();
  243. }
  244. // Only IF is set when a task boots.
  245. m_tss.eflags = 0x0202;
  246. word cs, ds, ss;
  247. if (isRing0()) {
  248. cs = 0x08;
  249. ds = 0x10;
  250. ss = 0x10;
  251. } else {
  252. cs = 0x1b;
  253. ds = 0x23;
  254. ss = 0x23;
  255. }
  256. m_tss.ds = ds;
  257. m_tss.es = ds;
  258. m_tss.fs = ds;
  259. m_tss.gs = ds;
  260. m_tss.ss = ss;
  261. m_tss.cs = cs;
  262. m_tss.cr3 = MemoryManager::the().pageDirectoryBase().get();
  263. if (isRing0()) {
  264. // FIXME: This memory is leaked.
  265. // But uh, there's also no kernel task termination, so I guess it's not technically leaked...
  266. dword stackBottom = (dword)kmalloc(defaultStackSize);
  267. m_stackTop = (stackBottom + defaultStackSize) & 0xffffff8;
  268. m_tss.esp = m_stackTop;
  269. } else {
  270. auto* region = allocateRegion(defaultStackSize, "stack");
  271. ASSERT(region);
  272. m_stackTop = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
  273. }
  274. m_tss.esp = m_stackTop;
  275. if (isRing3()) {
  276. // Ring3 tasks need a separate stack for Ring0.
  277. m_kernelStack = kmalloc(defaultStackSize);
  278. DWORD ring0StackTop = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
  279. m_tss.ss0 = 0x10;
  280. m_tss.esp0 = ring0StackTop;
  281. }
  282. // HACK: Ring2 SS in the TSS is the current PID.
  283. m_tss.ss2 = m_pid;
  284. m_farPtr.offset = 0x98765432;
  285. }
  286. Task::~Task()
  287. {
  288. InterruptDisabler disabler;
  289. system.nprocess--;
  290. delete [] m_ldtEntries;
  291. m_ldtEntries = nullptr;
  292. if (m_kernelStack) {
  293. kfree(m_kernelStack);
  294. m_kernelStack = nullptr;
  295. }
  296. }
  297. void Task::dumpRegions()
  298. {
  299. kprintf("Task %s(%u) regions:\n", name().characters(), pid());
  300. kprintf("BEGIN END SIZE NAME\n");
  301. for (auto& region : m_regions) {
  302. kprintf("%x -- %x %x %s\n",
  303. region->linearAddress.get(),
  304. region->linearAddress.offset(region->size - 1).get(),
  305. region->size,
  306. region->name.characters());
  307. }
  308. }
  309. void Task::sys$exit(int status)
  310. {
  311. cli();
  312. #ifdef TASK_DEBUG
  313. kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
  314. #endif
  315. setState(Exiting);
  316. MemoryManager::the().unmapRegionsForTask(*this);
  317. s_tasks->remove(this);
  318. if (!scheduleNewTask()) {
  319. kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
  320. HANG;
  321. }
  322. s_deadTasks->append(this);
  323. switchNow();
  324. }
  325. void Task::taskDidCrash(Task* crashedTask)
  326. {
  327. ASSERT_INTERRUPTS_DISABLED();
  328. crashedTask->setState(Crashing);
  329. crashedTask->dumpRegions();
  330. s_tasks->remove(crashedTask);
  331. MemoryManager::the().unmapRegionsForTask(*crashedTask);
  332. if (!scheduleNewTask()) {
  333. kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
  334. HANG;
  335. }
  336. s_deadTasks->append(crashedTask);
  337. switchNow();
  338. }
  339. void Task::doHouseKeeping()
  340. {
  341. InterruptDisabler disabler;
  342. if (s_deadTasks->isEmpty())
  343. return;
  344. Task* next = nullptr;
  345. for (auto* deadTask = s_deadTasks->head(); deadTask; deadTask = next) {
  346. next = deadTask->next();
  347. delete deadTask;
  348. }
  349. s_deadTasks->clear();
  350. }
  351. void yield()
  352. {
  353. if (!current) {
  354. kprintf( "PANIC: yield() with !current" );
  355. HANG;
  356. }
  357. //kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
  358. InterruptDisabler disabler;
  359. if (!scheduleNewTask())
  360. return;
  361. //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters());
  362. switchNow();
  363. }
  364. void switchNow()
  365. {
  366. Descriptor& descriptor = getGDTEntry(current->selector());
  367. descriptor.type = 9;
  368. flushGDT();
  369. asm("sti\n"
  370. "ljmp *(%%eax)\n"
  371. ::"a"(&current->farPtr())
  372. );
  373. }
  374. bool scheduleNewTask()
  375. {
  376. ASSERT_INTERRUPTS_DISABLED();
  377. if (!current) {
  378. // XXX: The first ever context_switch() goes to the idle task.
  379. // This to setup a reliable place we can return to.
  380. return contextSwitch(Task::kernelTask());
  381. }
  382. // Check and unblock tasks whose wait conditions have been met.
  383. for (auto* task = s_tasks->head(); task; task = task->next()) {
  384. if (task->state() == Task::BlockedSleep) {
  385. if (task->wakeupTime() <= system.uptime) {
  386. task->unblock();
  387. continue;
  388. }
  389. }
  390. if (task->state() == Task::BlockedWait) {
  391. if (!Task::fromPID(task->waitee())) {
  392. task->unblock();
  393. continue;
  394. }
  395. }
  396. if (task->state() == Task::BlockedRead) {
  397. ASSERT(task->m_fdBlockedOnRead != -1);
  398. if (task->m_fileHandles[task->m_fdBlockedOnRead]->hasDataAvailableForRead()) {
  399. task->unblock();
  400. continue;
  401. }
  402. }
  403. }
  404. #if 0
  405. kprintf("Scheduler choices:\n");
  406. for (auto* task = s_tasks->head(); task; task = task->next()) {
  407. if (task->state() == Task::BlockedWait || task->state() == Task::BlockedSleep)
  408. continue;
  409. kprintf("%w %s(%u)\n", task->state(), task->name().characters(), task->pid());
  410. }
  411. #endif
  412. auto* prevHead = s_tasks->head();
  413. for (;;) {
  414. // Move head to tail.
  415. s_tasks->append(s_tasks->removeHead());
  416. auto* task = s_tasks->head();
  417. if (task->state() == Task::Runnable || task->state() == Task::Running) {
  418. //kprintf("switch to %s (%p vs %p)\n", task->name().characters(), task, current);
  419. return contextSwitch(task);
  420. }
  421. if (task == prevHead) {
  422. // Back at task_head, nothing wants to run.
  423. kprintf("Nothing wants to run!\n");
  424. kprintf("PID OWNER STATE NSCHED NAME\n");
  425. for (auto* task = s_tasks->head(); task; task = task->next()) {
  426. kprintf("%w %w:%w %b %w %s\n",
  427. task->pid(),
  428. task->uid(),
  429. task->gid(),
  430. task->state(),
  431. task->timesScheduled(),
  432. task->name().characters());
  433. }
  434. kprintf("Switch to kernel task\n");
  435. return contextSwitch(Task::kernelTask());
  436. }
  437. }
  438. }
  439. static bool contextSwitch(Task* t)
  440. {
  441. //kprintf("c_s to %s (same:%u)\n", t->name().characters(), current == t);
  442. t->setTicksLeft(5);
  443. t->didSchedule();
  444. if (current == t)
  445. return false;
  446. // Some sanity checking to force a crash earlier.
  447. auto csRPL = t->tss().cs & 3;
  448. auto ssRPL = t->tss().ss & 3;
  449. if (csRPL != ssRPL) {
  450. kprintf("Fuckup! Switching from %s(%u) to %s(%u) has RPL mismatch\n",
  451. current->name().characters(), current->pid(),
  452. t->name().characters(), t->pid()
  453. );
  454. kprintf("code: %w:%x\n", t->tss().cs, t->tss().eip);
  455. kprintf(" stk: %w:%x\n", t->tss().ss, t->tss().esp);
  456. ASSERT(csRPL == ssRPL);
  457. }
  458. if (current) {
  459. // If the last task hasn't blocked (still marked as running),
  460. // mark it as runnable for the next round.
  461. if (current->state() == Task::Running)
  462. current->setState(Task::Runnable);
  463. bool success = MemoryManager::the().unmapRegionsForTask(*current);
  464. ASSERT(success);
  465. }
  466. bool success = MemoryManager::the().mapRegionsForTask(*t);
  467. ASSERT(success);
  468. current = t;
  469. t->setState(Task::Running);
  470. if (!t->selector())
  471. t->setSelector(allocateGDTEntry());
  472. auto& tssDescriptor = getGDTEntry(t->selector());
  473. tssDescriptor.limit_hi = 0;
  474. tssDescriptor.limit_lo = 0xFFFF;
  475. tssDescriptor.base_lo = (DWORD)(&t->tss()) & 0xFFFF;
  476. tssDescriptor.base_hi = ((DWORD)(&t->tss()) >> 16) & 0xFF;
  477. tssDescriptor.base_hi2 = ((DWORD)(&t->tss()) >> 24) & 0xFF;
  478. tssDescriptor.dpl = 0;
  479. tssDescriptor.segment_present = 1;
  480. tssDescriptor.granularity = 1;
  481. tssDescriptor.zero = 0;
  482. tssDescriptor.operation_size = 1;
  483. tssDescriptor.descriptor_type = 0;
  484. tssDescriptor.type = 11; // Busy TSS
  485. flushGDT();
  486. return true;
  487. }
  488. Task* Task::fromPID(pid_t pid)
  489. {
  490. for (auto* task = s_tasks->head(); task; task = task->next()) {
  491. if (task->pid() == pid)
  492. return task;
  493. }
  494. return nullptr;
  495. }
  496. FileHandle* Task::fileHandleIfExists(int fd)
  497. {
  498. if (fd < 0)
  499. return nullptr;
  500. if ((unsigned)fd < m_fileHandles.size())
  501. return m_fileHandles[fd].ptr();
  502. return nullptr;
  503. }
  504. ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
  505. {
  506. auto* handle = fileHandleIfExists(fd);
  507. if (!handle)
  508. return -1;
  509. return handle->get_dir_entries((byte*)buffer, size);
  510. }
  511. int Task::sys$seek(int fd, int offset)
  512. {
  513. auto* handle = fileHandleIfExists(fd);
  514. if (!handle)
  515. return -1;
  516. return handle->seek(offset, SEEK_SET);
  517. }
  518. ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
  519. {
  520. Task::checkSanity("Task::sys$read");
  521. #ifdef DEBUG_IO
  522. kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
  523. #endif
  524. auto* handle = fileHandleIfExists(fd);
  525. #ifdef DEBUG_IO
  526. kprintf("Task::sys$read: handle=%p\n", handle);
  527. #endif
  528. if (!handle) {
  529. kprintf("Task::sys$read: handle not found :(\n");
  530. return -1;
  531. }
  532. #ifdef DEBUG_IO
  533. kprintf("call read on handle=%p\n", handle);
  534. #endif
  535. if (handle->isBlocking()) {
  536. if (!handle->hasDataAvailableForRead()) {
  537. m_fdBlockedOnRead = fd;
  538. block(BlockedRead);
  539. yield();
  540. }
  541. }
  542. nread = handle->read((byte*)outbuf, nread);
  543. #ifdef DEBUG_IO
  544. kprintf("Task::sys$read: nread=%u\n", nread);
  545. #endif
  546. return nread;
  547. }
  548. int Task::sys$close(int fd)
  549. {
  550. auto* handle = fileHandleIfExists(fd);
  551. if (!handle)
  552. return -1;
  553. // FIXME: Implement.
  554. return 0;
  555. }
  556. int Task::sys$lstat(const char* path, void* statbuf)
  557. {
  558. auto handle = VirtualFileSystem::the().open(move(path));
  559. if (!handle)
  560. return -1;
  561. handle->stat((Unix::stat*)statbuf);
  562. return 0;
  563. }
  564. int Task::sys$getcwd(char* buffer, size_t size)
  565. {
  566. if (size < m_cwd.length() + 1) {
  567. // FIXME: return -ERANGE;
  568. return -1;
  569. }
  570. memcpy(buffer, m_cwd.characters(), m_cwd.length());
  571. buffer[m_cwd.length()] = '\0';
  572. return 0;
  573. }
  574. int Task::sys$open(const char* path, size_t pathLength)
  575. {
  576. Task::checkSanity("sys$open");
  577. #ifdef DEBUG_IO
  578. kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
  579. #endif
  580. auto* handle = openFile(String(path, pathLength));
  581. if (handle)
  582. return handle->fd();
  583. return -1;
  584. }
  585. FileHandle* Task::openFile(String&& path)
  586. {
  587. auto handle = VirtualFileSystem::the().open(move(path));
  588. if (!handle) {
  589. #ifdef DEBUG_IO
  590. kprintf("vfs::open() failed\n");
  591. #endif
  592. return nullptr;
  593. }
  594. handle->setFD(m_fileHandles.size());
  595. #ifdef DEBUG_IO
  596. kprintf("vfs::open() worked! handle=%p, fd=%d\n", handle.ptr(), handle->fd());
  597. #endif
  598. m_fileHandles.append(move(handle)); // FIXME: allow non-move Vector::append
  599. return m_fileHandles.last().ptr();
  600. }
  601. int Task::sys$kill(pid_t pid, int sig)
  602. {
  603. (void) sig;
  604. if (pid == 0) {
  605. // FIXME: Send to same-group processes.
  606. ASSERT(pid != 0);
  607. }
  608. if (pid == -1) {
  609. // FIXME: Send to all processes.
  610. ASSERT(pid != -1);
  611. }
  612. ASSERT_NOT_REACHED();
  613. Task* peer = Task::fromPID(pid);
  614. if (!peer) {
  615. // errno = ESRCH;
  616. return -1;
  617. }
  618. return -1;
  619. }
  620. uid_t Task::sys$getuid()
  621. {
  622. return m_uid;
  623. }
  624. gid_t Task::sys$getgid()
  625. {
  626. return m_gid;
  627. }
  628. pid_t Task::sys$getpid()
  629. {
  630. return m_pid;
  631. }
  632. pid_t Task::sys$waitpid(pid_t waitee)
  633. {
  634. InterruptDisabler disabler;
  635. if (!Task::fromPID(waitee))
  636. return -1;
  637. m_waitee = waitee;
  638. block(BlockedWait);
  639. yield();
  640. return m_waitee;
  641. }
  642. void Task::unblock()
  643. {
  644. ASSERT(m_state != Task::Runnable && m_state != Task::Running);
  645. system.nblocked--;
  646. m_state = Task::Runnable;
  647. }
  648. void Task::block(Task::State state)
  649. {
  650. ASSERT(current->state() == Task::Running);
  651. system.nblocked++;
  652. current->setState(state);
  653. }
  654. void block(Task::State state)
  655. {
  656. current->block(state);
  657. yield();
  658. }
  659. void sleep(DWORD ticks)
  660. {
  661. ASSERT(current->state() == Task::Running);
  662. current->setWakeupTime(system.uptime + ticks);
  663. current->block(Task::BlockedSleep);
  664. yield();
  665. }
  666. void Task::sys$sleep(DWORD ticks)
  667. {
  668. ASSERT(this == current);
  669. sleep(ticks);
  670. }
  671. Task* Task::kernelTask()
  672. {
  673. ASSERT(s_kernelTask);
  674. return s_kernelTask;
  675. }
  676. Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
  677. : linearAddress(a)
  678. , size(s)
  679. , zone(move(z))
  680. , name(move(n))
  681. {
  682. }
  683. Task::Region::~Region()
  684. {
  685. }