Task.cpp 30 KB

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