Task.cpp 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  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);
  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)
  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());
  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)
  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_parentPID(parentPID)
  331. {
  332. m_fileHandles.append(nullptr); // stdin
  333. m_fileHandles.append(nullptr); // stdout
  334. m_fileHandles.append(nullptr); // stderr
  335. m_nextRegion = LinearAddress(0x600000);
  336. memset(&m_tss, 0, sizeof(m_tss));
  337. if (isRing3()) {
  338. memset(&m_ldtEntries, 0, sizeof(m_ldtEntries));
  339. allocateLDT();
  340. }
  341. // Only IF is set when a task boots.
  342. m_tss.eflags = 0x0202;
  343. word cs, ds, ss;
  344. if (isRing0()) {
  345. cs = 0x08;
  346. ds = 0x10;
  347. ss = 0x10;
  348. } else {
  349. cs = 0x1b;
  350. ds = 0x23;
  351. ss = 0x23;
  352. }
  353. m_tss.ds = ds;
  354. m_tss.es = ds;
  355. m_tss.fs = ds;
  356. m_tss.gs = ds;
  357. m_tss.ss = ss;
  358. m_tss.cs = cs;
  359. m_tss.cr3 = MM.pageDirectoryBase().get();
  360. if (isRing0()) {
  361. // FIXME: This memory is leaked.
  362. // But uh, there's also no kernel task termination, so I guess it's not technically leaked...
  363. dword stackBottom = (dword)kmalloc(defaultStackSize);
  364. m_stackTop0 = (stackBottom + defaultStackSize) & 0xffffff8;
  365. m_tss.esp = m_stackTop0;
  366. } else {
  367. auto* region = allocateRegion(defaultStackSize, "stack");
  368. ASSERT(region);
  369. m_stackTop3 = region->linearAddress.offset(defaultStackSize).get() & 0xfffffff8;
  370. m_tss.esp = m_stackTop3;
  371. }
  372. if (isRing3()) {
  373. // Ring3 tasks need a separate stack for Ring0.
  374. m_kernelStack = kmalloc(defaultStackSize);
  375. m_stackTop0 = ((DWORD)m_kernelStack + defaultStackSize) & 0xffffff8;
  376. m_tss.ss0 = 0x10;
  377. m_tss.esp0 = m_stackTop0;
  378. }
  379. // HACK: Ring2 SS in the TSS is the current PID.
  380. m_tss.ss2 = m_pid;
  381. m_farPtr.offset = 0x98765432;
  382. ProcFileSystem::the().addProcess(*this);
  383. }
  384. Task::~Task()
  385. {
  386. InterruptDisabler disabler;
  387. ProcFileSystem::the().removeProcess(*this);
  388. system.nprocess--;
  389. delete [] m_ldtEntries;
  390. m_ldtEntries = nullptr;
  391. if (m_kernelStack) {
  392. kfree(m_kernelStack);
  393. m_kernelStack = nullptr;
  394. }
  395. }
  396. void Task::dumpRegions()
  397. {
  398. kprintf("Task %s(%u) regions:\n", name().characters(), pid());
  399. kprintf("BEGIN END SIZE NAME\n");
  400. for (auto& region : m_regions) {
  401. kprintf("%x -- %x %x %s\n",
  402. region->linearAddress.get(),
  403. region->linearAddress.offset(region->size - 1).get(),
  404. region->size,
  405. region->name.characters());
  406. }
  407. kprintf("Task %s(%u) subregions:\n", name().characters(), pid());
  408. kprintf("REGION OFFSET BEGIN END SIZE NAME\n");
  409. for (auto& subregion : m_subregions) {
  410. kprintf("%x %x %x -- %x %x %s\n",
  411. subregion->region->linearAddress.get(),
  412. subregion->offset,
  413. subregion->linearAddress.get(),
  414. subregion->linearAddress.offset(subregion->size - 1).get(),
  415. subregion->size,
  416. subregion->name.characters());
  417. }
  418. }
  419. void Task::sys$exit(int status)
  420. {
  421. cli();
  422. #ifdef TASK_DEBUG
  423. kprintf("sys$exit: %s(%u) exit with status %d\n", name().characters(), pid(), status);
  424. #endif
  425. setState(Exiting);
  426. MM.unmapRegionsForTask(*this);
  427. s_tasks->remove(this);
  428. for (auto* task = s_tasks->head(); task; task = task->next()) {
  429. if (task->waitee() == m_pid)
  430. task->m_waiteeStatus = status << 8;
  431. }
  432. if (!scheduleNewTask()) {
  433. kprintf("Task::sys$exit: Failed to schedule a new task :(\n");
  434. HANG;
  435. }
  436. s_deadTasks->append(this);
  437. switchNow();
  438. }
  439. void Task::taskDidCrash(Task* crashedTask)
  440. {
  441. ASSERT_INTERRUPTS_DISABLED();
  442. if (crashedTask->state() == Crashing) {
  443. kprintf("Double crash :(\n");
  444. HANG;
  445. }
  446. crashedTask->setState(Crashing);
  447. crashedTask->dumpRegions();
  448. s_tasks->remove(crashedTask);
  449. MM.unmapRegionsForTask(*crashedTask);
  450. if (!scheduleNewTask()) {
  451. kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
  452. HANG;
  453. }
  454. s_deadTasks->append(crashedTask);
  455. switchNow();
  456. }
  457. void Task::doHouseKeeping()
  458. {
  459. InterruptDisabler disabler;
  460. if (s_deadTasks->isEmpty())
  461. return;
  462. Task* next = nullptr;
  463. for (auto* deadTask = s_deadTasks->head(); deadTask; deadTask = next) {
  464. next = deadTask->next();
  465. delete deadTask;
  466. }
  467. s_deadTasks->clear();
  468. }
  469. void yield()
  470. {
  471. if (!current) {
  472. kprintf( "PANIC: yield() with !current" );
  473. HANG;
  474. }
  475. //kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
  476. InterruptDisabler disabler;
  477. if (!scheduleNewTask())
  478. return;
  479. //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters());
  480. switchNow();
  481. }
  482. void switchNow()
  483. {
  484. Descriptor& descriptor = getGDTEntry(current->selector());
  485. descriptor.type = 9;
  486. flushGDT();
  487. asm("sti\n"
  488. "ljmp *(%%eax)\n"
  489. ::"a"(&current->farPtr())
  490. );
  491. }
  492. bool scheduleNewTask()
  493. {
  494. ASSERT_INTERRUPTS_DISABLED();
  495. if (!current) {
  496. // XXX: The first ever context_switch() goes to the idle task.
  497. // This to setup a reliable place we can return to.
  498. return contextSwitch(Task::kernelTask());
  499. }
  500. // Check and unblock tasks whose wait conditions have been met.
  501. for (auto* task = s_tasks->head(); task; task = task->next()) {
  502. if (task->state() == Task::BlockedSleep) {
  503. if (task->wakeupTime() <= system.uptime) {
  504. task->unblock();
  505. continue;
  506. }
  507. }
  508. if (task->state() == Task::BlockedWait) {
  509. if (!Task::fromPID(task->waitee())) {
  510. task->unblock();
  511. continue;
  512. }
  513. }
  514. if (task->state() == Task::BlockedRead) {
  515. ASSERT(task->m_fdBlockedOnRead != -1);
  516. if (task->m_fileHandles[task->m_fdBlockedOnRead]->hasDataAvailableForRead()) {
  517. task->unblock();
  518. continue;
  519. }
  520. }
  521. }
  522. #ifdef SCHEDULER_DEBUG
  523. dbgprintf("Scheduler choices:\n");
  524. for (auto* task = s_tasks->head(); task; task = task->next()) {
  525. //if (task->state() == Task::BlockedWait || task->state() == Task::BlockedSleep)
  526. // continue;
  527. dbgprintf("%w %s(%u)\n", task->state(), task->name().characters(), task->pid());
  528. }
  529. #endif
  530. auto* prevHead = s_tasks->head();
  531. for (;;) {
  532. // Move head to tail.
  533. s_tasks->append(s_tasks->removeHead());
  534. auto* task = s_tasks->head();
  535. if (task->state() == Task::Runnable || task->state() == Task::Running) {
  536. #ifdef SCHEDULER_DEBUG
  537. dbgprintf("switch to %s(%u) (%p vs %p)\n", task->name().characters(), task->pid(), task, current);
  538. #endif
  539. return contextSwitch(task);
  540. }
  541. if (task == prevHead) {
  542. // Back at task_head, nothing wants to run.
  543. kprintf("Nothing wants to run!\n");
  544. kprintf("PID OWNER STATE NSCHED NAME\n");
  545. for (auto* task = s_tasks->head(); task; task = task->next()) {
  546. kprintf("%w %w:%w %b %w %s\n",
  547. task->pid(),
  548. task->uid(),
  549. task->gid(),
  550. task->state(),
  551. task->timesScheduled(),
  552. task->name().characters());
  553. }
  554. kprintf("Switch to kernel task\n");
  555. return contextSwitch(Task::kernelTask());
  556. }
  557. }
  558. }
  559. static bool contextSwitch(Task* t)
  560. {
  561. //kprintf("c_s to %s (same:%u)\n", t->name().characters(), current == t);
  562. t->setTicksLeft(5);
  563. t->didSchedule();
  564. if (current == t)
  565. return false;
  566. // Some sanity checking to force a crash earlier.
  567. auto csRPL = t->tss().cs & 3;
  568. auto ssRPL = t->tss().ss & 3;
  569. if (csRPL != ssRPL) {
  570. kprintf("Fuckup! Switching from %s(%u) to %s(%u) has RPL mismatch\n",
  571. current->name().characters(), current->pid(),
  572. t->name().characters(), t->pid()
  573. );
  574. kprintf("code: %w:%x\n", t->tss().cs, t->tss().eip);
  575. kprintf(" stk: %w:%x\n", t->tss().ss, t->tss().esp);
  576. ASSERT(csRPL == ssRPL);
  577. }
  578. if (current) {
  579. // If the last task hasn't blocked (still marked as running),
  580. // mark it as runnable for the next round.
  581. if (current->state() == Task::Running)
  582. current->setState(Task::Runnable);
  583. bool success = MM.unmapRegionsForTask(*current);
  584. ASSERT(success);
  585. }
  586. bool success = MM.mapRegionsForTask(*t);
  587. ASSERT(success);
  588. current = t;
  589. t->setState(Task::Running);
  590. if (!t->selector())
  591. t->setSelector(allocateGDTEntry());
  592. auto& tssDescriptor = getGDTEntry(t->selector());
  593. tssDescriptor.limit_hi = 0;
  594. tssDescriptor.limit_lo = 0xFFFF;
  595. tssDescriptor.base_lo = (DWORD)(&t->tss()) & 0xFFFF;
  596. tssDescriptor.base_hi = ((DWORD)(&t->tss()) >> 16) & 0xFF;
  597. tssDescriptor.base_hi2 = ((DWORD)(&t->tss()) >> 24) & 0xFF;
  598. tssDescriptor.dpl = 0;
  599. tssDescriptor.segment_present = 1;
  600. tssDescriptor.granularity = 1;
  601. tssDescriptor.zero = 0;
  602. tssDescriptor.operation_size = 1;
  603. tssDescriptor.descriptor_type = 0;
  604. tssDescriptor.type = 11; // Busy TSS
  605. flushGDT();
  606. return true;
  607. }
  608. Task* Task::fromPID(pid_t pid)
  609. {
  610. ASSERT_INTERRUPTS_DISABLED();
  611. for (auto* task = s_tasks->head(); task; task = task->next()) {
  612. if (task->pid() == pid)
  613. return task;
  614. }
  615. return nullptr;
  616. }
  617. FileHandle* Task::fileHandleIfExists(int fd)
  618. {
  619. if (fd < 0)
  620. return nullptr;
  621. if ((unsigned)fd < m_fileHandles.size())
  622. return m_fileHandles[fd].ptr();
  623. return nullptr;
  624. }
  625. ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
  626. {
  627. VALIDATE_USER_BUFFER(buffer, size);
  628. auto* handle = fileHandleIfExists(fd);
  629. if (!handle)
  630. return -1;
  631. return handle->get_dir_entries((byte*)buffer, size);
  632. }
  633. int Task::sys$seek(int fd, int offset)
  634. {
  635. auto* handle = fileHandleIfExists(fd);
  636. if (!handle)
  637. return -1;
  638. return handle->seek(offset, SEEK_SET);
  639. }
  640. ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
  641. {
  642. VALIDATE_USER_BUFFER(outbuf, nread);
  643. #ifdef DEBUG_IO
  644. kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
  645. #endif
  646. auto* handle = fileHandleIfExists(fd);
  647. #ifdef DEBUG_IO
  648. kprintf("Task::sys$read: handle=%p\n", handle);
  649. #endif
  650. if (!handle) {
  651. kprintf("Task::sys$read: handle not found :(\n");
  652. return -1;
  653. }
  654. #ifdef DEBUG_IO
  655. kprintf("call read on handle=%p\n", handle);
  656. #endif
  657. if (handle->isBlocking()) {
  658. if (!handle->hasDataAvailableForRead()) {
  659. m_fdBlockedOnRead = fd;
  660. block(BlockedRead);
  661. yield();
  662. }
  663. }
  664. nread = handle->read((byte*)outbuf, nread);
  665. #ifdef DEBUG_IO
  666. kprintf("Task::sys$read: nread=%u\n", nread);
  667. #endif
  668. return nread;
  669. }
  670. int Task::sys$close(int fd)
  671. {
  672. auto* handle = fileHandleIfExists(fd);
  673. if (!handle)
  674. return -1;
  675. // FIXME: Implement.
  676. return 0;
  677. }
  678. int Task::sys$lstat(const char* path, Unix::stat* statbuf)
  679. {
  680. VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
  681. int error;
  682. auto handle = VirtualFileSystem::the().open(move(path), error, O_NOFOLLOW_NOERROR, cwdInode());
  683. if (!handle)
  684. return error;
  685. handle->stat(statbuf);
  686. return 0;
  687. }
  688. int Task::sys$readlink(const char* path, char* buffer, size_t size)
  689. {
  690. VALIDATE_USER_BUFFER(path, strlen(path));
  691. VALIDATE_USER_BUFFER(buffer, size);
  692. int error;
  693. auto handle = VirtualFileSystem::the().open(path, error, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode());
  694. if (!handle)
  695. return error;
  696. if (!handle->metadata().isSymbolicLink())
  697. return -EINVAL;
  698. auto contents = handle->readEntireFile();
  699. if (!contents)
  700. return -EIO; // FIXME: Get a more detailed error from VFS.
  701. memcpy(buffer, contents.pointer(), min(size, contents.size()));
  702. if (contents.size() + 1 < size)
  703. buffer[contents.size()] = '\0';
  704. return 0;
  705. }
  706. int Task::sys$chdir(const char* path)
  707. {
  708. VALIDATE_USER_BUFFER(path, strlen(path));
  709. int error;
  710. auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode());
  711. if (!handle)
  712. return error;
  713. if (!handle->isDirectory())
  714. return -ENOTDIR;
  715. m_cwd = handle->vnode();
  716. return 0;
  717. }
  718. int Task::sys$getcwd(char* buffer, size_t size)
  719. {
  720. VALIDATE_USER_BUFFER(buffer, size);
  721. auto path = VirtualFileSystem::the().absolutePath(cwdInode());
  722. if (path.isNull())
  723. return -EINVAL;
  724. if (size < path.length() + 1)
  725. return -ERANGE;
  726. strcpy(buffer, path.characters());
  727. return -ENOTIMPL;
  728. }
  729. int Task::sys$open(const char* path, int options)
  730. {
  731. #ifdef DEBUG_IO
  732. kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
  733. #endif
  734. VALIDATE_USER_BUFFER(path, strlen(path));
  735. if (m_fileHandles.size() >= m_maxFileHandles)
  736. return -EMFILE;
  737. int error;
  738. auto handle = VirtualFileSystem::the().open(path, error, options, cwdInode());
  739. if (!handle)
  740. return error;
  741. if (options & O_DIRECTORY && !handle->isDirectory())
  742. return -ENOTDIR; // FIXME: This should be handled by VFS::open.
  743. int fd = m_fileHandles.size();
  744. handle->setFD(fd);
  745. m_fileHandles.append(move(handle));
  746. return fd;
  747. }
  748. int Task::sys$uname(utsname* buf)
  749. {
  750. VALIDATE_USER_BUFFER(buf, sizeof(utsname));
  751. strcpy(buf->sysname, "Serenity");
  752. strcpy(buf->release, "1.0-dev");
  753. strcpy(buf->version, "FIXME");
  754. strcpy(buf->machine, "i386");
  755. strcpy(buf->nodename, getHostname().characters());
  756. return 0;
  757. }
  758. int Task::sys$kill(pid_t pid, int sig)
  759. {
  760. (void) sig;
  761. if (pid == 0) {
  762. // FIXME: Send to same-group processes.
  763. ASSERT(pid != 0);
  764. }
  765. if (pid == -1) {
  766. // FIXME: Send to all processes.
  767. ASSERT(pid != -1);
  768. }
  769. ASSERT_NOT_REACHED();
  770. Task* peer = Task::fromPID(pid);
  771. if (!peer) {
  772. // errno = ESRCH;
  773. return -1;
  774. }
  775. return -1;
  776. }
  777. int Task::sys$sleep(unsigned seconds)
  778. {
  779. if (!seconds)
  780. return 0;
  781. sleep(seconds * TICKS_PER_SECOND);
  782. return 0;
  783. }
  784. int Task::sys$gettimeofday(timeval* tv)
  785. {
  786. VALIDATE_USER_BUFFER(tv, sizeof(tv));
  787. InterruptDisabler disabler;
  788. auto now = RTC::now();
  789. tv->tv_sec = now;
  790. tv->tv_usec = 0;
  791. return 0;
  792. }
  793. uid_t Task::sys$getuid()
  794. {
  795. return m_uid;
  796. }
  797. gid_t Task::sys$getgid()
  798. {
  799. return m_gid;
  800. }
  801. pid_t Task::sys$getpid()
  802. {
  803. return m_pid;
  804. }
  805. pid_t Task::sys$waitpid(pid_t waitee, int* wstatus, int options)
  806. {
  807. if (wstatus)
  808. VALIDATE_USER_BUFFER(wstatus, sizeof(int));
  809. InterruptDisabler disabler;
  810. if (!Task::fromPID(waitee))
  811. return -1;
  812. m_waitee = waitee;
  813. m_waiteeStatus = 0;
  814. block(BlockedWait);
  815. yield();
  816. if (wstatus)
  817. *wstatus = m_waiteeStatus;
  818. return m_waitee;
  819. }
  820. void Task::unblock()
  821. {
  822. ASSERT(m_state != Task::Runnable && m_state != Task::Running);
  823. system.nblocked--;
  824. m_state = Task::Runnable;
  825. }
  826. void Task::block(Task::State state)
  827. {
  828. ASSERT(current->state() == Task::Running);
  829. system.nblocked++;
  830. current->setState(state);
  831. }
  832. void block(Task::State state)
  833. {
  834. current->block(state);
  835. yield();
  836. }
  837. void sleep(DWORD ticks)
  838. {
  839. ASSERT(current->state() == Task::Running);
  840. current->setWakeupTime(system.uptime + ticks);
  841. current->block(Task::BlockedSleep);
  842. yield();
  843. }
  844. Task* Task::kernelTask()
  845. {
  846. ASSERT(s_kernelTask);
  847. return s_kernelTask;
  848. }
  849. Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
  850. : linearAddress(a)
  851. , size(s)
  852. , zone(move(z))
  853. , name(move(n))
  854. {
  855. }
  856. Task::Region::~Region()
  857. {
  858. }
  859. Task::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
  860. : region(r)
  861. , offset(o)
  862. , size(s)
  863. , linearAddress(l)
  864. , name(move(n))
  865. {
  866. }
  867. Task::Subregion::~Subregion()
  868. {
  869. }
  870. bool Task::isValidAddressForKernel(LinearAddress laddr) const
  871. {
  872. InterruptDisabler disabler;
  873. if (laddr.get() >= ksyms().first().address && laddr.get() <= ksyms().last().address)
  874. return true;
  875. if (is_kmalloc_address((void*)laddr.get()))
  876. return true;
  877. return isValidAddressForUser(laddr);
  878. }
  879. bool Task::isValidAddressForUser(LinearAddress laddr) const
  880. {
  881. InterruptDisabler disabler;
  882. for (auto& region: m_regions) {
  883. if (laddr >= region->linearAddress && laddr < region->linearAddress.offset(region->size))
  884. return true;
  885. }
  886. for (auto& subregion: m_subregions) {
  887. if (laddr >= subregion->linearAddress && laddr < subregion->linearAddress.offset(subregion->size))
  888. return true;
  889. }
  890. return false;
  891. }