Task.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  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. #include "i8253.h"
  14. #include "RTC.h"
  15. #include "ProcFileSystem.h"
  16. #include <AK/StdLib.h>
  17. //#define DEBUG_IO
  18. //#define TASK_DEBUG
  19. //#define SCHEDULER_DEBUG
  20. #define VALIDATE_USER_BUFFER(b, s) \
  21. do { \
  22. LinearAddress laddr((dword)(b)); \
  23. if (!isValidAddressForUser(laddr) || !isValidAddressForUser(laddr.offset((s) - 1))) \
  24. return -EFAULT; \
  25. } while(0)
  26. static const DWORD defaultStackSize = 16384;
  27. Task* current;
  28. Task* s_kernelTask;
  29. static pid_t next_pid;
  30. static InlineLinkedList<Task>* s_tasks;
  31. static InlineLinkedList<Task>* s_deadTasks;
  32. static String* s_hostname;
  33. static String& hostnameStorage(InterruptDisabler&)
  34. {
  35. ASSERT(s_hostname);
  36. return *s_hostname;
  37. }
  38. static String getHostname()
  39. {
  40. InterruptDisabler disabler;
  41. return hostnameStorage(disabler).isolatedCopy();
  42. }
  43. static bool contextSwitch(Task*);
  44. static void redoKernelTaskTSS()
  45. {
  46. if (!s_kernelTask->selector())
  47. s_kernelTask->setSelector(allocateGDTEntry());
  48. auto& tssDescriptor = getGDTEntry(s_kernelTask->selector());
  49. tssDescriptor.setBase(&s_kernelTask->tss());
  50. tssDescriptor.setLimit(0xffff);
  51. tssDescriptor.dpl = 0;
  52. tssDescriptor.segment_present = 1;
  53. tssDescriptor.granularity = 1;
  54. tssDescriptor.zero = 0;
  55. tssDescriptor.operation_size = 1;
  56. tssDescriptor.descriptor_type = 0;
  57. tssDescriptor.type = 9;
  58. flushGDT();
  59. }
  60. void Task::prepForIRETToNewTask()
  61. {
  62. redoKernelTaskTSS();
  63. s_kernelTask->tss().backlink = current->selector();
  64. loadTaskRegister(s_kernelTask->selector());
  65. }
  66. void Task::initialize()
  67. {
  68. current = nullptr;
  69. next_pid = 0;
  70. s_tasks = new InlineLinkedList<Task>;
  71. s_deadTasks = new InlineLinkedList<Task>;
  72. s_kernelTask = Task::createKernelTask(nullptr, "colonel");
  73. s_hostname = new String("birx");
  74. redoKernelTaskTSS();
  75. loadTaskRegister(s_kernelTask->selector());
  76. }
  77. #ifdef TASK_SANITY_CHECKS
  78. void Task::checkSanity(const char* msg)
  79. {
  80. char ch = current->name()[0];
  81. kprintf("<%p> %s{%u}%b [%d] :%b: sanity check <%s>\n",
  82. current->name().characters(),
  83. current->name().characters(),
  84. current->name().length(),
  85. current->name()[current->name().length() - 1],
  86. current->pid(), ch, msg ? msg : "");
  87. ASSERT((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'));
  88. }
  89. #endif
  90. void Task::allocateLDT()
  91. {
  92. ASSERT(!m_tss.ldt);
  93. static const WORD numLDTEntries = 4;
  94. WORD newLDTSelector = allocateGDTEntry();
  95. m_ldtEntries = new Descriptor[numLDTEntries];
  96. #if 0
  97. kprintf("new ldt selector = %x\n", newLDTSelector);
  98. kprintf("new ldt table at = %p\n", m_ldtEntries);
  99. kprintf("new ldt table size = %u\n", (numLDTEntries * 8) - 1);
  100. #endif
  101. Descriptor& ldt = getGDTEntry(newLDTSelector);
  102. ldt.setBase(m_ldtEntries);
  103. ldt.setLimit(numLDTEntries * 8 - 1);
  104. ldt.dpl = 0;
  105. ldt.segment_present = 1;
  106. ldt.granularity = 0;
  107. ldt.zero = 0;
  108. ldt.operation_size = 1;
  109. ldt.descriptor_type = 0;
  110. ldt.type = Descriptor::LDT;
  111. m_tss.ldt = newLDTSelector;
  112. }
  113. Vector<Task*> Task::allTasks()
  114. {
  115. InterruptDisabler disabler;
  116. Vector<Task*> tasks;
  117. tasks.ensureCapacity(s_tasks->sizeSlow());
  118. for (auto* task = s_tasks->head(); task; task = task->next())
  119. tasks.append(task);
  120. return tasks;
  121. }
  122. Task::Region* Task::allocateRegion(size_t size, String&& name)
  123. {
  124. // FIXME: This needs sanity checks. What if this overlaps existing regions?
  125. auto zone = MM.createZone(size);
  126. ASSERT(zone);
  127. m_regions.append(adopt(*new Region(m_nextRegion, size, move(zone), move(name))));
  128. m_nextRegion = m_nextRegion.offset(size).offset(16384);
  129. return m_regions.last().ptr();
  130. }
  131. bool Task::deallocateRegion(Region& region)
  132. {
  133. InterruptDisabler disabler;
  134. for (size_t i = 0; i < m_regions.size(); ++i) {
  135. if (m_regions[i].ptr() == &region) {
  136. MM.unmapRegion(*this, region);
  137. m_regions.remove(i);
  138. return true;
  139. }
  140. }
  141. return false;
  142. }
  143. Task::Region* Task::regionFromRange(LinearAddress laddr, size_t size)
  144. {
  145. for (auto& region : m_regions) {
  146. if (region->linearAddress == laddr && region->size == size)
  147. return region.ptr();
  148. }
  149. return nullptr;
  150. }
  151. int Task::sys$set_mmap_name(void* addr, size_t size, const char* name)
  152. {
  153. VALIDATE_USER_BUFFER(name, strlen(name));
  154. auto* region = regionFromRange(LinearAddress((dword)addr), size);
  155. if (!region)
  156. return -EINVAL;
  157. region->name = name;
  158. return 0;
  159. }
  160. void* Task::sys$mmap(void* addr, size_t size)
  161. {
  162. // FIXME: Implement mapping at a client-preferred address.
  163. ASSERT(addr == nullptr);
  164. auto* region = allocateRegion(size, "mmap");
  165. if (!region)
  166. return (void*)-1;
  167. MM.mapRegion(*this, *region);
  168. return (void*)region->linearAddress.get();
  169. }
  170. int Task::sys$munmap(void* addr, size_t size)
  171. {
  172. auto* region = regionFromRange(LinearAddress((dword)addr), size);
  173. if (!region)
  174. return -1;
  175. if (!deallocateRegion(*region))
  176. return -1;
  177. return 0;
  178. }
  179. int Task::sys$gethostname(char* buffer, size_t size)
  180. {
  181. VALIDATE_USER_BUFFER(buffer, size);
  182. auto hostname = getHostname();
  183. if (size < (hostname.length() + 1))
  184. return -ENAMETOOLONG;
  185. memcpy(buffer, hostname.characters(), size);
  186. return 0;
  187. }
  188. int Task::sys$spawn(const char* path, const char** args)
  189. {
  190. int error = 0;
  191. auto* child = Task::createUserTask(path, m_uid, m_gid, m_pid, error, args, m_tty);
  192. if (child)
  193. return child->pid();
  194. return error;
  195. }
  196. Task* Task::createUserTask(const String& path, uid_t uid, gid_t gid, pid_t parentPID, int& error, const char** args, TTY* tty)
  197. {
  198. auto parts = path.split('/');
  199. if (parts.isEmpty()) {
  200. error = -ENOENT;
  201. return nullptr;
  202. }
  203. RetainPtr<VirtualFileSystem::Node> cwd;
  204. {
  205. InterruptDisabler disabler;
  206. if (auto* parentTask = Task::fromPID(parentPID))
  207. cwd = parentTask->m_cwd.copyRef();
  208. if (!cwd)
  209. cwd = VirtualFileSystem::the().root();
  210. }
  211. auto handle = VirtualFileSystem::the().open(path, error, 0, cwd ? cwd->inode : InodeIdentifier());
  212. if (!handle)
  213. return nullptr;
  214. if (!handle->metadata().mayExecute(uid, gid)) {
  215. error = -EACCES;
  216. return nullptr;
  217. }
  218. auto elfData = handle->readEntireFile();
  219. if (!elfData) {
  220. error = -EIO; // FIXME: Get a more detailed error from VFS.
  221. return nullptr;
  222. }
  223. Vector<String> taskArguments;
  224. if (args) {
  225. for (size_t i = 0; args[i]; ++i) {
  226. taskArguments.append(args[i]);
  227. }
  228. } else {
  229. taskArguments.append(parts.last());
  230. }
  231. InterruptDisabler disabler; // FIXME: Get rid of this, jesus christ. This "critical" section is HUGE.
  232. Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3, move(cwd), handle->vnode(), tty);
  233. t->m_arguments = move(taskArguments);
  234. ExecSpace space;
  235. Region* region = nullptr;
  236. space.hookableAlloc = [&] (const String& name, size_t size) {
  237. if (!size)
  238. return (void*)nullptr;
  239. size = ((size / 4096) + 1) * 4096;
  240. region = t->allocateRegion(size, String(name));
  241. ASSERT(region);
  242. MM.mapRegion(*t, *region);
  243. return (void*)region->linearAddress.asPtr();
  244. };
  245. bool success = space.loadELF(move(elfData));
  246. if (!success) {
  247. // FIXME: This is ugly. If we need to do this, it should be at a different level.
  248. MM.unmapRegionsForTask(*t);
  249. MM.mapRegionsForTask(*current);
  250. delete t;
  251. kprintf("Failure loading ELF %s\n", path.characters());
  252. error = -ENOEXEC;
  253. return nullptr;
  254. }
  255. space.forEachArea([&] (const String& name, dword offset, size_t size, LinearAddress laddr) {
  256. if (laddr.isNull())
  257. return;
  258. dword roundedOffset = offset & 0xfffff000;
  259. size_t roundedSize = 4096 * ceilDiv((offset - roundedOffset) + size, 4096u);
  260. LinearAddress roundedLaddr = laddr;
  261. roundedLaddr.mask(0xfffff000);
  262. t->m_subregions.append(make<Subregion>(*region, roundedOffset, roundedSize, roundedLaddr, String(name)));
  263. #ifdef SUBREGION_DEBUG
  264. kprintf(" req subregion %s (offset: %u, size: %u) @ %p\n", name.characters(), offset, size, laddr.get());
  265. kprintf("actual subregion %s (offset: %u, size: %u) @ %p\n", name.characters(), roundedOffset, roundedSize, roundedLaddr.get());
  266. #endif
  267. MM.mapSubregion(*t, *t->m_subregions.last());
  268. });
  269. t->m_tss.eip = (dword)space.symbolPtr("_start");
  270. if (!t->m_tss.eip) {
  271. // FIXME: This is ugly. If we need to do this, it should be at a different level.
  272. MM.unmapRegionsForTask(*t);
  273. MM.mapRegionsForTask(*current);
  274. delete t;
  275. error = -ENOEXEC;
  276. return nullptr;
  277. }
  278. // FIXME: This is ugly. If we need to do this, it should be at a different level.
  279. MM.unmapRegionsForTask(*t);
  280. MM.mapRegionsForTask(*current);
  281. s_tasks->prepend(t);
  282. system.nprocess++;
  283. #ifdef TASK_DEBUG
  284. kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
  285. #endif
  286. error = 0;
  287. return t;
  288. }
  289. int Task::sys$get_arguments(int* argc, char*** argv)
  290. {
  291. auto* region = allocateRegion(4096, "argv");
  292. if (!region)
  293. return -ENOMEM;
  294. MM.mapRegion(*this, *region);
  295. char* argpage = (char*)region->linearAddress.get();
  296. *argc = m_arguments.size();
  297. *argv = (char**)argpage;
  298. char* bufptr = argpage + (sizeof(char*) * m_arguments.size());
  299. for (size_t i = 0; i < m_arguments.size(); ++i) {
  300. (*argv)[i] = bufptr;
  301. memcpy(bufptr, m_arguments[i].characters(), m_arguments[i].length());
  302. bufptr += m_arguments[i].length();
  303. *(bufptr++) = '\0';
  304. }
  305. return 0;
  306. }
  307. Task* Task::createKernelTask(void (*e)(), String&& name)
  308. {
  309. Task* task = new Task(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);
  310. task->m_tss.eip = (dword)e;
  311. if (task->pid() != 0) {
  312. InterruptDisabler disabler;
  313. s_tasks->prepend(task);
  314. system.nprocess++;
  315. #ifdef TASK_DEBUG
  316. kprintf("Kernel task %u (%s) spawned @ %p\n", task->pid(), task->name().characters(), task->m_tss.eip);
  317. #endif
  318. }
  319. return task;
  320. }
  321. Task::Task(String&& name, uid_t uid, gid_t gid, pid_t parentPID, RingLevel ring, RetainPtr<VirtualFileSystem::Node>&& cwd, RetainPtr<VirtualFileSystem::Node>&& executable, TTY* tty)
  322. : m_name(move(name))
  323. , m_pid(next_pid++)
  324. , m_uid(uid)
  325. , m_gid(gid)
  326. , m_state(Runnable)
  327. , m_ring(ring)
  328. , m_cwd(move(cwd))
  329. , m_executable(move(executable))
  330. , m_tty(tty)
  331. , m_parentPID(parentPID)
  332. {
  333. if (tty) {
  334. m_fileHandles.append(tty->open(O_RDONLY)); // stdin
  335. m_fileHandles.append(tty->open(O_WRONLY)); // stdout
  336. m_fileHandles.append(tty->open(O_WRONLY)); // stderr
  337. } else {
  338. m_fileHandles.append(nullptr); // stdin
  339. m_fileHandles.append(nullptr); // stdout
  340. m_fileHandles.append(nullptr); // stderr
  341. }
  342. m_nextRegion = LinearAddress(0x600000);
  343. memset(&m_tss, 0, sizeof(m_tss));
  344. if (isRing3()) {
  345. memset(&m_ldtEntries, 0, sizeof(m_ldtEntries));
  346. allocateLDT();
  347. }
  348. // Only IF is set when a task boots.
  349. m_tss.eflags = 0x0202;
  350. word cs, ds, ss;
  351. if (isRing0()) {
  352. cs = 0x08;
  353. ds = 0x10;
  354. ss = 0x10;
  355. } else {
  356. cs = 0x1b;
  357. ds = 0x23;
  358. ss = 0x23;
  359. }
  360. m_tss.ds = ds;
  361. m_tss.es = ds;
  362. m_tss.fs = ds;
  363. m_tss.gs = ds;
  364. m_tss.ss = ss;
  365. m_tss.cs = cs;
  366. m_tss.cr3 = MM.pageDirectoryBase().get();
  367. if (isRing0()) {
  368. // FIXME: This memory is leaked.
  369. // But uh, there's also no kernel task termination, so I guess it's not technically leaked...
  370. dword stackBottom = (dword)kmalloc(defaultStackSize);
  371. m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8;
  372. m_tss.esp = m_stackTop0;
  373. } else {
  374. auto* region = allocateRegion(defaultStackSize, "stack");
  375. ASSERT(region);
  376. m_stackTop3 = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
  377. m_tss.esp = m_stackTop3;
  378. }
  379. if (isRing3()) {
  380. // Ring3 tasks need a separate stack for Ring0.
  381. m_kernelStack = kmalloc(defaultStackSize);
  382. m_stackTop0 = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
  383. m_tss.ss0 = 0x10;
  384. m_tss.esp0 = m_stackTop0;
  385. }
  386. // HACK: Ring2 SS in the TSS is the current PID.
  387. m_tss.ss2 = m_pid;
  388. m_farPtr.offset = 0x98765432;
  389. ProcFileSystem::the().addProcess(*this);
  390. }
  391. Task::~Task()
  392. {
  393. InterruptDisabler disabler;
  394. ProcFileSystem::the().removeProcess(*this);
  395. system.nprocess--;
  396. delete [] m_ldtEntries;
  397. m_ldtEntries = nullptr;
  398. if (m_kernelStack) {
  399. kfree(m_kernelStack);
  400. m_kernelStack = nullptr;
  401. }
  402. }
  403. void Task::dumpRegions()
  404. {
  405. kprintf("Task %s(%u) regions:\n", name().characters(), pid());
  406. kprintf("BEGIN END SIZE NAME\n");
  407. for (auto& region : m_regions) {
  408. kprintf("%x -- %x %x %s\n",
  409. region->linearAddress.get(),
  410. region->linearAddress.offset(region->size - 1).get(),
  411. region->size,
  412. region->name.characters());
  413. }
  414. kprintf("Task %s(%u) subregions:\n", name().characters(), pid());
  415. kprintf("REGION OFFSET BEGIN END SIZE NAME\n");
  416. for (auto& subregion : m_subregions) {
  417. kprintf("%x %x %x -- %x %x %s\n",
  418. subregion->region->linearAddress.get(),
  419. subregion->offset,
  420. subregion->linearAddress.get(),
  421. subregion->linearAddress.offset(subregion->size - 1).get(),
  422. subregion->size,
  423. subregion->name.characters());
  424. }
  425. }
  426. void Task::sys$exit(int status)
  427. {
  428. cli();
  429. #ifdef TASK_DEBUG
  430. kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
  431. #endif
  432. setState(Exiting);
  433. MM.unmapRegionsForTask(*this);
  434. s_tasks->remove(this);
  435. for (auto* task = s_tasks->head(); task; task = task->next()) {
  436. if (task->waitee() == m_pid)
  437. task->m_waiteeStatus = status << 8;
  438. }
  439. if (!scheduleNewTask()) {
  440. kprintf("Task::sys$exit: Failed to schedule a new task :(\n");
  441. HANG;
  442. }
  443. s_deadTasks->append(this);
  444. switchNow();
  445. }
  446. void Task::taskDidCrash(Task* crashedTask)
  447. {
  448. ASSERT_INTERRUPTS_DISABLED();
  449. if (crashedTask->state() == Crashing) {
  450. kprintf("Double crash :(\n");
  451. HANG;
  452. }
  453. crashedTask->setState(Crashing);
  454. crashedTask->dumpRegions();
  455. s_tasks->remove(crashedTask);
  456. MM.unmapRegionsForTask(*crashedTask);
  457. if (!scheduleNewTask()) {
  458. kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
  459. HANG;
  460. }
  461. s_deadTasks->append(crashedTask);
  462. switchNow();
  463. }
  464. void Task::doHouseKeeping()
  465. {
  466. InterruptDisabler disabler;
  467. if (s_deadTasks->isEmpty())
  468. return;
  469. Task* next = nullptr;
  470. for (auto* deadTask = s_deadTasks->head(); deadTask; deadTask = next) {
  471. next = deadTask->next();
  472. delete deadTask;
  473. }
  474. s_deadTasks->clear();
  475. }
  476. void yield()
  477. {
  478. if (!current) {
  479. kprintf( "PANIC: yield() with !current" );
  480. HANG;
  481. }
  482. //kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
  483. InterruptDisabler disabler;
  484. if (!scheduleNewTask())
  485. return;
  486. //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters());
  487. switchNow();
  488. }
  489. void switchNow()
  490. {
  491. Descriptor& descriptor = getGDTEntry(current->selector());
  492. descriptor.type = 9;
  493. flushGDT();
  494. asm("sti\n"
  495. "ljmp *(%%eax)\n"
  496. ::"a"(&current->farPtr())
  497. );
  498. }
  499. bool scheduleNewTask()
  500. {
  501. ASSERT_INTERRUPTS_DISABLED();
  502. if (!current) {
  503. // XXX: The first ever context_switch() goes to the idle task.
  504. // This to setup a reliable place we can return to.
  505. return contextSwitch(Task::kernelTask());
  506. }
  507. // Check and unblock tasks whose wait conditions have been met.
  508. for (auto* task = s_tasks->head(); task; task = task->next()) {
  509. if (task->state() == Task::BlockedSleep) {
  510. if (task->wakeupTime() <= system.uptime) {
  511. task->unblock();
  512. continue;
  513. }
  514. }
  515. if (task->state() == Task::BlockedWait) {
  516. if (!Task::fromPID(task->waitee())) {
  517. task->unblock();
  518. continue;
  519. }
  520. }
  521. if (task->state() == Task::BlockedRead) {
  522. ASSERT(task->m_fdBlockedOnRead != -1);
  523. if (task->m_fileHandles[task->m_fdBlockedOnRead]->hasDataAvailableForRead()) {
  524. task->unblock();
  525. continue;
  526. }
  527. }
  528. }
  529. #ifdef SCHEDULER_DEBUG
  530. dbgprintf("Scheduler choices:\n");
  531. for (auto* task = s_tasks->head(); task; task = task->next()) {
  532. //if (task->state() == Task::BlockedWait || task->state() == Task::BlockedSleep)
  533. // continue;
  534. dbgprintf("%w %s(%u)\n", task->state(), task->name().characters(), task->pid());
  535. }
  536. #endif
  537. auto* prevHead = s_tasks->head();
  538. for (;;) {
  539. // Move head to tail.
  540. s_tasks->append(s_tasks->removeHead());
  541. auto* task = s_tasks->head();
  542. if (task->state() == Task::Runnable || task->state() == Task::Running) {
  543. #ifdef SCHEDULER_DEBUG
  544. dbgprintf("switch to %s(%u) (%p vs %p)\n", task->name().characters(), task->pid(), task, current);
  545. #endif
  546. return contextSwitch(task);
  547. }
  548. if (task == prevHead) {
  549. // Back at task_head, nothing wants to run.
  550. kprintf("Nothing wants to run!\n");
  551. kprintf("PID OWNER STATE NSCHED NAME\n");
  552. for (auto* task = s_tasks->head(); task; task = task->next()) {
  553. kprintf("%w %w:%w %b %w %s\n",
  554. task->pid(),
  555. task->uid(),
  556. task->gid(),
  557. task->state(),
  558. task->timesScheduled(),
  559. task->name().characters());
  560. }
  561. kprintf("Switch to kernel task\n");
  562. return contextSwitch(Task::kernelTask());
  563. }
  564. }
  565. }
  566. static bool contextSwitch(Task* t)
  567. {
  568. //kprintf("c_s to %s (same:%u)\n", t->name().characters(), current == t);
  569. t->setTicksLeft(5);
  570. t->didSchedule();
  571. if (current == t)
  572. return false;
  573. // Some sanity checking to force a crash earlier.
  574. auto csRPL = t->tss().cs & 3;
  575. auto ssRPL = t->tss().ss & 3;
  576. if (csRPL != ssRPL) {
  577. kprintf("Fuckup! Switching from %s(%u) to %s(%u) has RPL mismatch\n",
  578. current->name().characters(), current->pid(),
  579. t->name().characters(), t->pid()
  580. );
  581. kprintf("code: %w:%x\n", t->tss().cs, t->tss().eip);
  582. kprintf(" stk: %w:%x\n", t->tss().ss, t->tss().esp);
  583. ASSERT(csRPL == ssRPL);
  584. }
  585. if (current) {
  586. // If the last task hasn't blocked (still marked as running),
  587. // mark it as runnable for the next round.
  588. if (current->state() == Task::Running)
  589. current->setState(Task::Runnable);
  590. bool success = MM.unmapRegionsForTask(*current);
  591. ASSERT(success);
  592. }
  593. bool success = MM.mapRegionsForTask(*t);
  594. ASSERT(success);
  595. current = t;
  596. t->setState(Task::Running);
  597. if (!t->selector())
  598. t->setSelector(allocateGDTEntry());
  599. auto& tssDescriptor = getGDTEntry(t->selector());
  600. tssDescriptor.limit_hi = 0;
  601. tssDescriptor.limit_lo = 0xFFFF;
  602. tssDescriptor.base_lo = (DWORD)(&t->tss()) & 0xFFFF;
  603. tssDescriptor.base_hi = ((DWORD)(&t->tss()) >> 16) & 0xFF;
  604. tssDescriptor.base_hi2 = ((DWORD)(&t->tss()) >> 24) & 0xFF;
  605. tssDescriptor.dpl = 0;
  606. tssDescriptor.segment_present = 1;
  607. tssDescriptor.granularity = 1;
  608. tssDescriptor.zero = 0;
  609. tssDescriptor.operation_size = 1;
  610. tssDescriptor.descriptor_type = 0;
  611. tssDescriptor.type = 11; // Busy TSS
  612. flushGDT();
  613. return true;
  614. }
  615. Task* Task::fromPID(pid_t pid)
  616. {
  617. ASSERT_INTERRUPTS_DISABLED();
  618. for (auto* task = s_tasks->head(); task; task = task->next()) {
  619. if (task->pid() == pid)
  620. return task;
  621. }
  622. return nullptr;
  623. }
  624. FileHandle* Task::fileHandleIfExists(int fd)
  625. {
  626. if (fd < 0)
  627. return nullptr;
  628. if ((unsigned)fd < m_fileHandles.size())
  629. return m_fileHandles[fd].ptr();
  630. return nullptr;
  631. }
  632. ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
  633. {
  634. VALIDATE_USER_BUFFER(buffer, size);
  635. auto* handle = fileHandleIfExists(fd);
  636. if (!handle)
  637. return -EBADF;
  638. return handle->get_dir_entries((byte*)buffer, size);
  639. }
  640. int Task::sys$seek(int fd, int offset)
  641. {
  642. auto* handle = fileHandleIfExists(fd);
  643. if (!handle)
  644. return -EBADF;
  645. return handle->seek(offset, SEEK_SET);
  646. }
  647. int Task::sys$ttyname_r(int fd, char* buffer, size_t size)
  648. {
  649. VALIDATE_USER_BUFFER(buffer, size);
  650. auto* handle = fileHandleIfExists(fd);
  651. if (!handle)
  652. return -EBADF;
  653. if (!handle->isTTY())
  654. return -ENOTTY;
  655. auto ttyName = handle->tty()->ttyName();
  656. if (size < ttyName.length() + 1)
  657. return -ERANGE;
  658. strcpy(buffer, ttyName.characters());
  659. return 0;
  660. }
  661. ssize_t Task::sys$write(int fd, const void* data, size_t size)
  662. {
  663. VALIDATE_USER_BUFFER(data, size);
  664. #ifdef DEBUG_IO
  665. kprintf("Task::sys$write: called(%d, %p, %u)\n", fd, data, size);
  666. #endif
  667. auto* handle = fileHandleIfExists(fd);
  668. #ifdef DEBUG_IO
  669. kprintf("Task::sys$write: handle=%p\n", handle);
  670. #endif
  671. if (!handle)
  672. return -EBADF;
  673. auto nwritten = handle->write((const byte*)data, size);
  674. #ifdef DEBUG_IO
  675. kprintf("Task::sys$write: nwritten=%u\n", nwritten);
  676. #endif
  677. return nwritten;
  678. }
  679. ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
  680. {
  681. VALIDATE_USER_BUFFER(outbuf, nread);
  682. #ifdef DEBUG_IO
  683. kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
  684. #endif
  685. auto* handle = fileHandleIfExists(fd);
  686. #ifdef DEBUG_IO
  687. kprintf("Task::sys$read: handle=%p\n", handle);
  688. #endif
  689. if (!handle)
  690. return -EBADF;
  691. if (handle->isBlocking()) {
  692. if (!handle->hasDataAvailableForRead()) {
  693. m_fdBlockedOnRead = fd;
  694. block(BlockedRead);
  695. yield();
  696. }
  697. }
  698. nread = handle->read((byte*)outbuf, nread);
  699. #ifdef DEBUG_IO
  700. kprintf("Task::sys$read: nread=%u\n", nread);
  701. #endif
  702. return nread;
  703. }
  704. int Task::sys$close(int fd)
  705. {
  706. auto* handle = fileHandleIfExists(fd);
  707. if (!handle)
  708. return -EBADF;
  709. // FIXME: Implement.
  710. return 0;
  711. }
  712. int Task::sys$lstat(const char* path, Unix::stat* statbuf)
  713. {
  714. VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
  715. int error;
  716. auto handle = VirtualFileSystem::the().open(move(path), error, O_NOFOLLOW_NOERROR, cwdInode());
  717. if (!handle)
  718. return error;
  719. handle->stat(statbuf);
  720. return 0;
  721. }
  722. int Task::sys$readlink(const char* path, char* buffer, size_t size)
  723. {
  724. VALIDATE_USER_BUFFER(path, strlen(path));
  725. VALIDATE_USER_BUFFER(buffer, size);
  726. int error;
  727. auto handle = VirtualFileSystem::the().open(path, error, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode());
  728. if (!handle)
  729. return error;
  730. if (!handle->metadata().isSymbolicLink())
  731. return -EINVAL;
  732. auto contents = handle->readEntireFile();
  733. if (!contents)
  734. return -EIO; // FIXME: Get a more detailed error from VFS.
  735. memcpy(buffer, contents.pointer(), min(size, contents.size()));
  736. if (contents.size() + 1 < size)
  737. buffer[contents.size()] = '\0';
  738. return 0;
  739. }
  740. int Task::sys$chdir(const char* path)
  741. {
  742. VALIDATE_USER_BUFFER(path, strlen(path));
  743. int error;
  744. auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode());
  745. if (!handle)
  746. return error;
  747. if (!handle->isDirectory())
  748. return -ENOTDIR;
  749. m_cwd = handle->vnode();
  750. return 0;
  751. }
  752. int Task::sys$getcwd(char* buffer, size_t size)
  753. {
  754. VALIDATE_USER_BUFFER(buffer, size);
  755. auto path = VirtualFileSystem::the().absolutePath(cwdInode());
  756. if (path.isNull())
  757. return -EINVAL;
  758. if (size < path.length() + 1)
  759. return -ERANGE;
  760. strcpy(buffer, path.characters());
  761. return -ENOTIMPL;
  762. }
  763. int Task::sys$open(const char* path, int options)
  764. {
  765. #ifdef DEBUG_IO
  766. kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
  767. #endif
  768. VALIDATE_USER_BUFFER(path, strlen(path));
  769. if (m_fileHandles.size() >= m_maxFileHandles)
  770. return -EMFILE;
  771. int error;
  772. auto handle = VirtualFileSystem::the().open(path, error, options, cwdInode());
  773. if (!handle)
  774. return error;
  775. if (options & O_DIRECTORY && !handle->isDirectory())
  776. return -ENOTDIR; // FIXME: This should be handled by VFS::open.
  777. int fd = m_fileHandles.size();
  778. handle->setFD(fd);
  779. m_fileHandles.append(move(handle));
  780. return fd;
  781. }
  782. int Task::sys$uname(utsname* buf)
  783. {
  784. VALIDATE_USER_BUFFER(buf, sizeof(utsname));
  785. strcpy(buf->sysname, "Serenity");
  786. strcpy(buf->release, "1.0-dev");
  787. strcpy(buf->version, "FIXME");
  788. strcpy(buf->machine, "i386");
  789. strcpy(buf->nodename, getHostname().characters());
  790. return 0;
  791. }
  792. int Task::sys$kill(pid_t pid, int sig)
  793. {
  794. (void) sig;
  795. if (pid == 0) {
  796. // FIXME: Send to same-group processes.
  797. ASSERT(pid != 0);
  798. }
  799. if (pid == -1) {
  800. // FIXME: Send to all processes.
  801. ASSERT(pid != -1);
  802. }
  803. ASSERT_NOT_REACHED();
  804. Task* peer = Task::fromPID(pid);
  805. if (!peer) {
  806. // errno = ESRCH;
  807. return -1;
  808. }
  809. return -1;
  810. }
  811. int Task::sys$sleep(unsigned seconds)
  812. {
  813. if (!seconds)
  814. return 0;
  815. sleep(seconds * TICKS_PER_SECOND);
  816. return 0;
  817. }
  818. int Task::sys$gettimeofday(timeval* tv)
  819. {
  820. VALIDATE_USER_BUFFER(tv, sizeof(tv));
  821. InterruptDisabler disabler;
  822. auto now = RTC::now();
  823. tv->tv_sec = now;
  824. tv->tv_usec = 0;
  825. return 0;
  826. }
  827. uid_t Task::sys$getuid()
  828. {
  829. return m_uid;
  830. }
  831. gid_t Task::sys$getgid()
  832. {
  833. return m_gid;
  834. }
  835. pid_t Task::sys$getpid()
  836. {
  837. return m_pid;
  838. }
  839. pid_t Task::sys$waitpid(pid_t waitee, int* wstatus, int options)
  840. {
  841. if (wstatus)
  842. VALIDATE_USER_BUFFER(wstatus, sizeof(int));
  843. InterruptDisabler disabler;
  844. if (!Task::fromPID(waitee))
  845. return -1;
  846. m_waitee = waitee;
  847. m_waiteeStatus = 0;
  848. block(BlockedWait);
  849. yield();
  850. if (wstatus)
  851. *wstatus = m_waiteeStatus;
  852. return m_waitee;
  853. }
  854. void Task::unblock()
  855. {
  856. ASSERT(m_state != Task::Runnable && m_state != Task::Running);
  857. system.nblocked--;
  858. m_state = Task::Runnable;
  859. }
  860. void Task::block(Task::State state)
  861. {
  862. ASSERT(current->state() == Task::Running);
  863. system.nblocked++;
  864. current->setState(state);
  865. }
  866. void block(Task::State state)
  867. {
  868. current->block(state);
  869. yield();
  870. }
  871. void sleep(DWORD ticks)
  872. {
  873. ASSERT(current->state() == Task::Running);
  874. current->setWakeupTime(system.uptime + ticks);
  875. current->block(Task::BlockedSleep);
  876. yield();
  877. }
  878. Task* Task::kernelTask()
  879. {
  880. ASSERT(s_kernelTask);
  881. return s_kernelTask;
  882. }
  883. Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
  884. : linearAddress(a)
  885. , size(s)
  886. , zone(move(z))
  887. , name(move(n))
  888. {
  889. }
  890. Task::Region::~Region()
  891. {
  892. }
  893. Task::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
  894. : region(r)
  895. , offset(o)
  896. , size(s)
  897. , linearAddress(l)
  898. , name(move(n))
  899. {
  900. }
  901. Task::Subregion::~Subregion()
  902. {
  903. }
  904. bool Task::isValidAddressForKernel(LinearAddress laddr) const
  905. {
  906. InterruptDisabler disabler;
  907. if (laddr.get() >= ksyms().first().address && laddr.get() <= ksyms().last().address)
  908. return true;
  909. if (is_kmalloc_address((void*)laddr.get()))
  910. return true;
  911. return isValidAddressForUser(laddr);
  912. }
  913. bool Task::isValidAddressForUser(LinearAddress laddr) const
  914. {
  915. InterruptDisabler disabler;
  916. for (auto& region: m_regions) {
  917. if (laddr >= region->linearAddress && laddr < region->linearAddress.offset(region->size))
  918. return true;
  919. }
  920. for (auto& subregion: m_subregions) {
  921. if (laddr >= subregion->linearAddress && laddr < subregion->linearAddress.offset(subregion->size))
  922. return true;
  923. }
  924. return false;
  925. }