Task.cpp 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  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. KernelPagingScope pagingScope;
  245. Task* t = new Task(parts.takeLast(), uid, gid, parentPID, Ring3, move(cwd), handle->vnode(), tty);
  246. t->m_arguments = move(taskArguments);
  247. t->m_initialEnvironment = move(taskEnvironment);
  248. ExecSpace space;
  249. Region* region = nullptr;
  250. byte* region_alias = nullptr;
  251. space.hookableAlloc = [&] (const String& name, size_t size) {
  252. if (!size)
  253. return (void*)nullptr;
  254. size = ((size / 4096) + 1) * 4096; // FIXME: Use ceil_div?
  255. region = t->allocateRegion(size, String(name));
  256. ASSERT(region);
  257. region_alias = MM.create_kernel_alias_for_region(*region);
  258. return (void*)region_alias;
  259. };
  260. bool success = space.loadELF(move(elfData));
  261. if (!success) {
  262. MM.remove_kernel_alias_for_region(*region, region_alias);
  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.remove_kernel_alias_for_region(*region, region_alias);
  286. delete t;
  287. error = -ENOEXEC;
  288. return nullptr;
  289. }
  290. MM.remove_kernel_alias_for_region(*region, region_alias);
  291. MM.mapRegionsForTask(*t);
  292. s_tasks->prepend(t);
  293. system.nprocess++;
  294. #ifdef TASK_DEBUG
  295. kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
  296. #endif
  297. error = 0;
  298. return t;
  299. }
  300. int Task::sys$get_environment(char*** environ)
  301. {
  302. auto* region = allocateRegion(4096, "environ");
  303. if (!region)
  304. return -ENOMEM;
  305. MM.mapRegion(*this, *region);
  306. char* envpage = (char*)region->linearAddress.get();
  307. *environ = (char**)envpage;
  308. char* bufptr = envpage + (sizeof(char*) * (m_initialEnvironment.size() + 1));
  309. for (size_t i = 0; i < m_initialEnvironment.size(); ++i) {
  310. (*environ)[i] = bufptr;
  311. memcpy(bufptr, m_initialEnvironment[i].characters(), m_initialEnvironment[i].length());
  312. bufptr += m_initialEnvironment[i].length();
  313. *(bufptr++) = '\0';
  314. }
  315. (*environ)[m_initialEnvironment.size()] = nullptr;
  316. return 0;
  317. }
  318. int Task::sys$get_arguments(int* argc, char*** argv)
  319. {
  320. auto* region = allocateRegion(4096, "argv");
  321. if (!region)
  322. return -ENOMEM;
  323. MM.mapRegion(*this, *region);
  324. char* argpage = (char*)region->linearAddress.get();
  325. *argc = m_arguments.size();
  326. *argv = (char**)argpage;
  327. char* bufptr = argpage + (sizeof(char*) * m_arguments.size());
  328. for (size_t i = 0; i < m_arguments.size(); ++i) {
  329. (*argv)[i] = bufptr;
  330. memcpy(bufptr, m_arguments[i].characters(), m_arguments[i].length());
  331. bufptr += m_arguments[i].length();
  332. *(bufptr++) = '\0';
  333. }
  334. return 0;
  335. }
  336. Task* Task::createKernelTask(void (*e)(), String&& name)
  337. {
  338. Task* task = new Task(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);
  339. task->m_tss.eip = (dword)e;
  340. if (task->pid() != 0) {
  341. InterruptDisabler disabler;
  342. s_tasks->prepend(task);
  343. system.nprocess++;
  344. #ifdef TASK_DEBUG
  345. kprintf("Kernel task %u (%s) spawned @ %p\n", task->pid(), task->name().characters(), task->m_tss.eip);
  346. #endif
  347. }
  348. return task;
  349. }
  350. 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)
  351. : m_name(move(name))
  352. , m_pid(next_pid++)
  353. , m_uid(uid)
  354. , m_gid(gid)
  355. , m_state(Runnable)
  356. , m_ring(ring)
  357. , m_cwd(move(cwd))
  358. , m_executable(move(executable))
  359. , m_tty(tty)
  360. , m_parentPID(parentPID)
  361. {
  362. m_pageDirectory = (dword*)kmalloc_page_aligned(4096);
  363. MM.populate_page_directory(*this);
  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(0x10000000);
  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 = (dword)m_pageDirectory;
  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. s_tasks->remove(this);
  473. notify_waiters(m_pid, status, 0);
  474. if (!scheduleNewTask()) {
  475. kprintf("Task::sys$exit: Failed to schedule a new task :(\n");
  476. HANG;
  477. }
  478. s_deadTasks->append(this);
  479. switchNow();
  480. }
  481. void Task::murder(int signal)
  482. {
  483. ASSERT_INTERRUPTS_DISABLED();
  484. bool wasCurrent = current == this;
  485. setState(Exiting);
  486. s_tasks->remove(this);
  487. notify_waiters(m_pid, 0, signal);
  488. if (wasCurrent) {
  489. kprintf("Current task committing suicide!\n");
  490. if (!scheduleNewTask()) {
  491. kprintf("Task::murder: Failed to schedule a new task :(\n");
  492. HANG;
  493. }
  494. }
  495. s_deadTasks->append(this);
  496. if (wasCurrent)
  497. switchNow();
  498. }
  499. void Task::taskDidCrash(Task* crashedTask)
  500. {
  501. ASSERT_INTERRUPTS_DISABLED();
  502. if (crashedTask->state() == Crashing) {
  503. kprintf("Double crash :(\n");
  504. HANG;
  505. }
  506. crashedTask->setState(Crashing);
  507. crashedTask->dumpRegions();
  508. s_tasks->remove(crashedTask);
  509. notify_waiters(crashedTask->m_pid, 0, SIGSEGV);
  510. if (!scheduleNewTask()) {
  511. kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
  512. HANG;
  513. }
  514. s_deadTasks->append(crashedTask);
  515. switchNow();
  516. }
  517. void Task::doHouseKeeping()
  518. {
  519. InterruptDisabler disabler;
  520. if (s_deadTasks->isEmpty())
  521. return;
  522. Task* next = nullptr;
  523. for (auto* deadTask = s_deadTasks->head(); deadTask; deadTask = next) {
  524. next = deadTask->next();
  525. delete deadTask;
  526. }
  527. s_deadTasks->clear();
  528. }
  529. void yield()
  530. {
  531. if (!current) {
  532. kprintf( "PANIC: yield() with !current" );
  533. HANG;
  534. }
  535. //kprintf("%s<%u> yield()\n", current->name().characters(), current->pid());
  536. InterruptDisabler disabler;
  537. if (!scheduleNewTask())
  538. return;
  539. //kprintf("yield() jumping to new task: %x (%s)\n", current->farPtr().selector, current->name().characters());
  540. switchNow();
  541. }
  542. void switchNow()
  543. {
  544. Descriptor& descriptor = getGDTEntry(current->selector());
  545. descriptor.type = 9;
  546. flushGDT();
  547. asm("sti\n"
  548. "ljmp *(%%eax)\n"
  549. ::"a"(&current->farPtr())
  550. );
  551. }
  552. bool scheduleNewTask()
  553. {
  554. ASSERT_INTERRUPTS_DISABLED();
  555. if (!current) {
  556. // XXX: The first ever context_switch() goes to the idle task.
  557. // This to setup a reliable place we can return to.
  558. return contextSwitch(Task::kernelTask());
  559. }
  560. // Check and unblock tasks whose wait conditions have been met.
  561. for (auto* task = s_tasks->head(); task; task = task->next()) {
  562. if (task->state() == Task::BlockedSleep) {
  563. if (task->wakeupTime() <= system.uptime) {
  564. task->unblock();
  565. continue;
  566. }
  567. }
  568. if (task->state() == Task::BlockedWait) {
  569. if (!Task::fromPID(task->waitee())) {
  570. task->unblock();
  571. continue;
  572. }
  573. }
  574. if (task->state() == Task::BlockedRead) {
  575. ASSERT(task->m_fdBlockedOnRead != -1);
  576. if (task->m_fileHandles[task->m_fdBlockedOnRead]->hasDataAvailableForRead()) {
  577. task->unblock();
  578. continue;
  579. }
  580. }
  581. }
  582. #ifdef SCHEDULER_DEBUG
  583. dbgprintf("Scheduler choices:\n");
  584. for (auto* task = s_tasks->head(); task; task = task->next()) {
  585. //if (task->state() == Task::BlockedWait || task->state() == Task::BlockedSleep)
  586. // continue;
  587. dbgprintf("%w %s(%u)\n", task->state(), task->name().characters(), task->pid());
  588. }
  589. #endif
  590. auto* prevHead = s_tasks->head();
  591. for (;;) {
  592. // Move head to tail.
  593. s_tasks->append(s_tasks->removeHead());
  594. auto* task = s_tasks->head();
  595. if (task->state() == Task::Runnable || task->state() == Task::Running) {
  596. #ifdef SCHEDULER_DEBUG
  597. dbgprintf("switch to %s(%u) (%p vs %p)\n", task->name().characters(), task->pid(), task, current);
  598. #endif
  599. return contextSwitch(task);
  600. }
  601. if (task == prevHead) {
  602. // Back at task_head, nothing wants to run.
  603. kprintf("Nothing wants to run!\n");
  604. kprintf("PID OWNER STATE NSCHED NAME\n");
  605. for (auto* task = s_tasks->head(); task; task = task->next()) {
  606. kprintf("%w %w:%w %b %w %s\n",
  607. task->pid(),
  608. task->uid(),
  609. task->gid(),
  610. task->state(),
  611. task->timesScheduled(),
  612. task->name().characters());
  613. }
  614. kprintf("Switch to kernel task\n");
  615. return contextSwitch(Task::kernelTask());
  616. }
  617. }
  618. }
  619. static bool contextSwitch(Task* t)
  620. {
  621. t->setTicksLeft(5);
  622. t->didSchedule();
  623. if (current == t)
  624. return false;
  625. #ifdef SCHEDULER_DEBUG
  626. // Some sanity checking to force a crash earlier.
  627. auto csRPL = t->tss().cs & 3;
  628. auto ssRPL = t->tss().ss & 3;
  629. if (csRPL != ssRPL) {
  630. kprintf("Fuckup! Switching from %s(%u) to %s(%u) has RPL mismatch\n",
  631. current->name().characters(), current->pid(),
  632. t->name().characters(), t->pid()
  633. );
  634. kprintf("code: %w:%x\n", t->tss().cs, t->tss().eip);
  635. kprintf(" stk: %w:%x\n", t->tss().ss, t->tss().esp);
  636. ASSERT(csRPL == ssRPL);
  637. }
  638. #endif
  639. if (current) {
  640. // If the last task hasn't blocked (still marked as running),
  641. // mark it as runnable for the next round.
  642. if (current->state() == Task::Running)
  643. current->setState(Task::Runnable);
  644. }
  645. current = t;
  646. t->setState(Task::Running);
  647. if (!t->selector()) {
  648. t->setSelector(allocateGDTEntry());
  649. auto& descriptor = getGDTEntry(t->selector());
  650. descriptor.setBase(&t->tss());
  651. descriptor.setLimit(0xffff);
  652. descriptor.dpl = 0;
  653. descriptor.segment_present = 1;
  654. descriptor.granularity = 1;
  655. descriptor.zero = 0;
  656. descriptor.operation_size = 1;
  657. descriptor.descriptor_type = 0;
  658. }
  659. auto& descriptor = getGDTEntry(t->selector());
  660. descriptor.type = 11; // Busy TSS
  661. flushGDT();
  662. return true;
  663. }
  664. Task* Task::fromPID(pid_t pid)
  665. {
  666. ASSERT_INTERRUPTS_DISABLED();
  667. for (auto* task = s_tasks->head(); task; task = task->next()) {
  668. if (task->pid() == pid)
  669. return task;
  670. }
  671. return nullptr;
  672. }
  673. FileHandle* Task::fileHandleIfExists(int fd)
  674. {
  675. if (fd < 0)
  676. return nullptr;
  677. if ((unsigned)fd < m_fileHandles.size())
  678. return m_fileHandles[fd].ptr();
  679. return nullptr;
  680. }
  681. ssize_t Task::sys$get_dir_entries(int fd, void* buffer, size_t size)
  682. {
  683. VALIDATE_USER_BUFFER(buffer, size);
  684. auto* handle = fileHandleIfExists(fd);
  685. if (!handle)
  686. return -EBADF;
  687. return handle->get_dir_entries((byte*)buffer, size);
  688. }
  689. int Task::sys$lseek(int fd, off_t offset, int whence)
  690. {
  691. auto* handle = fileHandleIfExists(fd);
  692. if (!handle)
  693. return -EBADF;
  694. return handle->seek(offset, whence);
  695. }
  696. int Task::sys$ttyname_r(int fd, char* buffer, size_t size)
  697. {
  698. VALIDATE_USER_BUFFER(buffer, size);
  699. auto* handle = fileHandleIfExists(fd);
  700. if (!handle)
  701. return -EBADF;
  702. if (!handle->isTTY())
  703. return -ENOTTY;
  704. auto ttyName = handle->tty()->ttyName();
  705. if (size < ttyName.length() + 1)
  706. return -ERANGE;
  707. strcpy(buffer, ttyName.characters());
  708. return 0;
  709. }
  710. ssize_t Task::sys$write(int fd, const void* data, size_t size)
  711. {
  712. VALIDATE_USER_BUFFER(data, size);
  713. #ifdef DEBUG_IO
  714. kprintf("Task::sys$write: called(%d, %p, %u)\n", fd, data, size);
  715. #endif
  716. auto* handle = fileHandleIfExists(fd);
  717. #ifdef DEBUG_IO
  718. kprintf("Task::sys$write: handle=%p\n", handle);
  719. #endif
  720. if (!handle)
  721. return -EBADF;
  722. auto nwritten = handle->write((const byte*)data, size);
  723. #ifdef DEBUG_IO
  724. kprintf("Task::sys$write: nwritten=%u\n", nwritten);
  725. #endif
  726. return nwritten;
  727. }
  728. ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
  729. {
  730. VALIDATE_USER_BUFFER(outbuf, nread);
  731. #ifdef DEBUG_IO
  732. kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
  733. #endif
  734. auto* handle = fileHandleIfExists(fd);
  735. #ifdef DEBUG_IO
  736. kprintf("Task::sys$read: handle=%p\n", handle);
  737. #endif
  738. if (!handle)
  739. return -EBADF;
  740. if (handle->isBlocking()) {
  741. if (!handle->hasDataAvailableForRead()) {
  742. m_fdBlockedOnRead = fd;
  743. block(BlockedRead);
  744. yield();
  745. }
  746. }
  747. nread = handle->read((byte*)outbuf, nread);
  748. #ifdef DEBUG_IO
  749. kprintf("Task::sys$read: nread=%u\n", nread);
  750. #endif
  751. return nread;
  752. }
  753. int Task::sys$close(int fd)
  754. {
  755. auto* handle = fileHandleIfExists(fd);
  756. if (!handle)
  757. return -EBADF;
  758. // FIXME: Implement.
  759. return 0;
  760. }
  761. int Task::sys$lstat(const char* path, Unix::stat* statbuf)
  762. {
  763. VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
  764. int error;
  765. auto handle = VirtualFileSystem::the().open(move(path), error, O_NOFOLLOW_NOERROR, cwdInode());
  766. if (!handle)
  767. return error;
  768. handle->stat(statbuf);
  769. return 0;
  770. }
  771. int Task::sys$stat(const char* path, Unix::stat* statbuf)
  772. {
  773. VALIDATE_USER_BUFFER(statbuf, sizeof(Unix::stat));
  774. int error;
  775. auto handle = VirtualFileSystem::the().open(move(path), error, 0, cwdInode());
  776. if (!handle)
  777. return error;
  778. handle->stat(statbuf);
  779. return 0;
  780. }
  781. int Task::sys$readlink(const char* path, char* buffer, size_t size)
  782. {
  783. VALIDATE_USER_BUFFER(path, strlen(path));
  784. VALIDATE_USER_BUFFER(buffer, size);
  785. int error;
  786. auto handle = VirtualFileSystem::the().open(path, error, O_RDONLY | O_NOFOLLOW_NOERROR, cwdInode());
  787. if (!handle)
  788. return error;
  789. if (!handle->metadata().isSymbolicLink())
  790. return -EINVAL;
  791. auto contents = handle->readEntireFile();
  792. if (!contents)
  793. return -EIO; // FIXME: Get a more detailed error from VFS.
  794. memcpy(buffer, contents.pointer(), min(size, contents.size()));
  795. if (contents.size() + 1 < size)
  796. buffer[contents.size()] = '\0';
  797. return 0;
  798. }
  799. int Task::sys$chdir(const char* path)
  800. {
  801. VALIDATE_USER_BUFFER(path, strlen(path));
  802. int error;
  803. auto handle = VirtualFileSystem::the().open(path, error, 0, cwdInode());
  804. if (!handle)
  805. return error;
  806. if (!handle->isDirectory())
  807. return -ENOTDIR;
  808. m_cwd = handle->vnode();
  809. return 0;
  810. }
  811. int Task::sys$getcwd(char* buffer, size_t size)
  812. {
  813. VALIDATE_USER_BUFFER(buffer, size);
  814. auto path = VirtualFileSystem::the().absolutePath(cwdInode());
  815. if (path.isNull())
  816. return -EINVAL;
  817. if (size < path.length() + 1)
  818. return -ERANGE;
  819. strcpy(buffer, path.characters());
  820. return -ENOTIMPL;
  821. }
  822. int Task::sys$open(const char* path, int options)
  823. {
  824. #ifdef DEBUG_IO
  825. kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
  826. #endif
  827. VALIDATE_USER_BUFFER(path, strlen(path));
  828. if (m_fileHandles.size() >= m_maxFileHandles)
  829. return -EMFILE;
  830. int error;
  831. auto handle = VirtualFileSystem::the().open(path, error, options, cwdInode());
  832. if (!handle)
  833. return error;
  834. if (options & O_DIRECTORY && !handle->isDirectory())
  835. return -ENOTDIR; // FIXME: This should be handled by VFS::open.
  836. int fd = m_fileHandles.size();
  837. handle->setFD(fd);
  838. m_fileHandles.append(move(handle));
  839. return fd;
  840. }
  841. int Task::sys$uname(utsname* buf)
  842. {
  843. VALIDATE_USER_BUFFER(buf, sizeof(utsname));
  844. strcpy(buf->sysname, "Serenity");
  845. strcpy(buf->release, "1.0-dev");
  846. strcpy(buf->version, "FIXME");
  847. strcpy(buf->machine, "i386");
  848. strcpy(buf->nodename, getHostname().characters());
  849. return 0;
  850. }
  851. int Task::sys$kill(pid_t pid, int sig)
  852. {
  853. (void) sig;
  854. if (pid == 0) {
  855. // FIXME: Send to same-group processes.
  856. ASSERT(pid != 0);
  857. }
  858. if (pid == -1) {
  859. // FIXME: Send to all processes.
  860. ASSERT(pid != -1);
  861. }
  862. ASSERT(pid != current->pid()); // FIXME: Support this scenario.
  863. InterruptDisabler disabler;
  864. auto* peer = Task::fromPID(pid);
  865. if (!peer)
  866. return -ESRCH;
  867. if (sig == SIGKILL) {
  868. peer->murder(SIGKILL);
  869. return 0;
  870. } else {
  871. ASSERT_NOT_REACHED();
  872. }
  873. return -1;
  874. }
  875. int Task::sys$sleep(unsigned seconds)
  876. {
  877. if (!seconds)
  878. return 0;
  879. sleep(seconds * TICKS_PER_SECOND);
  880. return 0;
  881. }
  882. int Task::sys$gettimeofday(timeval* tv)
  883. {
  884. VALIDATE_USER_BUFFER(tv, sizeof(tv));
  885. InterruptDisabler disabler;
  886. auto now = RTC::now();
  887. tv->tv_sec = now;
  888. tv->tv_usec = 0;
  889. return 0;
  890. }
  891. uid_t Task::sys$getuid()
  892. {
  893. return m_uid;
  894. }
  895. gid_t Task::sys$getgid()
  896. {
  897. return m_gid;
  898. }
  899. pid_t Task::sys$getpid()
  900. {
  901. return m_pid;
  902. }
  903. pid_t Task::sys$waitpid(pid_t waitee, int* wstatus, int options)
  904. {
  905. if (wstatus)
  906. VALIDATE_USER_BUFFER(wstatus, sizeof(int));
  907. InterruptDisabler disabler;
  908. if (!Task::fromPID(waitee))
  909. return -1;
  910. m_waitee = waitee;
  911. m_waiteeStatus = 0;
  912. block(BlockedWait);
  913. yield();
  914. if (wstatus)
  915. *wstatus = m_waiteeStatus;
  916. return m_waitee;
  917. }
  918. void Task::unblock()
  919. {
  920. ASSERT(m_state != Task::Runnable && m_state != Task::Running);
  921. system.nblocked--;
  922. m_state = Task::Runnable;
  923. }
  924. void Task::block(Task::State state)
  925. {
  926. ASSERT(current->state() == Task::Running);
  927. system.nblocked++;
  928. current->setState(state);
  929. }
  930. void block(Task::State state)
  931. {
  932. current->block(state);
  933. yield();
  934. }
  935. void sleep(DWORD ticks)
  936. {
  937. ASSERT(current->state() == Task::Running);
  938. current->setWakeupTime(system.uptime + ticks);
  939. current->block(Task::BlockedSleep);
  940. yield();
  941. }
  942. Task* Task::kernelTask()
  943. {
  944. ASSERT(s_kernelTask);
  945. return s_kernelTask;
  946. }
  947. Task::Region::Region(LinearAddress a, size_t s, RetainPtr<Zone>&& z, String&& n)
  948. : linearAddress(a)
  949. , size(s)
  950. , zone(move(z))
  951. , name(move(n))
  952. {
  953. }
  954. Task::Region::~Region()
  955. {
  956. }
  957. Task::Subregion::Subregion(Region& r, dword o, size_t s, LinearAddress l, String&& n)\
  958. : region(r)
  959. , offset(o)
  960. , size(s)
  961. , linearAddress(l)
  962. , name(move(n))
  963. {
  964. }
  965. Task::Subregion::~Subregion()
  966. {
  967. }
  968. bool Task::isValidAddressForKernel(LinearAddress laddr) const
  969. {
  970. InterruptDisabler disabler;
  971. if (laddr.get() >= ksyms().first().address && laddr.get() <= ksyms().last().address)
  972. return true;
  973. if (is_kmalloc_address((void*)laddr.get()))
  974. return true;
  975. return isValidAddressForUser(laddr);
  976. }
  977. bool Task::isValidAddressForUser(LinearAddress laddr) const
  978. {
  979. InterruptDisabler disabler;
  980. for (auto& region: m_regions) {
  981. if (laddr >= region->linearAddress && laddr < region->linearAddress.offset(region->size))
  982. return true;
  983. }
  984. for (auto& subregion: m_subregions) {
  985. if (laddr >= subregion->linearAddress && laddr < subregion->linearAddress.offset(subregion->size))
  986. return true;
  987. }
  988. return false;
  989. }