Пример #1
0
void sleep(int ticks)
{
	if (getCurrentThread() == NULL)
	{
		// not ready to wait!
		uint64_t then = getUptime() + (uint64_t)ticks;
		while (getUptime() < then);
	}
	else
	{
		uint64_t then = getUptime() + (uint64_t)ticks;
		uint64_t nanoThen = then * (uint64_t)1000000;

		cli();
		lockSched();
		TimedEvent ev;
		timedPost(&ev, nanoThen);
		
		while (getNanotime() <= nanoThen)
		{
			waitThread(getCurrentThread());
			unlockSched();
			kyield();
			
			cli();
			lockSched();
		};
		
		timedCancel(&ev);
		unlockSched();
		sti();
	};
};
Пример #2
0
void onTick()
{
	lockSched();
	
	int doResched = 0;
	while (1)
	{
		if (timedEvents == NULL) break;
		if (getNanotime() <= timedEvents->nanotime) break;
		
		TimedEvent *ev = timedEvents;
		Thread *thread = ev->thread;
		timedEvents = ev->next;
		if (timedEvents != NULL) timedEvents->prev = NULL;
		ev->prev = ev->next = NULL;
		doResched = doResched || signalThread(thread);
	};
	
	unlockSched();
	if (doResched) kyield();
};
Пример #3
0
int pollThread(Regs *regs, int pid, int *stat_loc, int flags)
{
	if (kernelStatus != KERNEL_RUNNING)
	{
		currentThread->therrno = EPERM;
		return -1;
	};

	int sigcnt = getCurrentThread()->sigcnt;

	lockSched();
	ASM("cli");
	Thread *threadToKill = NULL;
	Thread *thread = currentThread->next;
	while (thread != currentThread)
	{
		if (thread->pidParent == currentThread->pid)
		{
			if ((thread->pid == pid) || (pid == -1))
			{
				if (thread->flags & THREAD_TERMINATED)
				{
					threadToKill = thread;
					*stat_loc = thread->status;

					// unlink from the runqueue
					thread->prev->next = thread->next;
					thread->next->prev = thread->prev;

					break;
				};
			};
		};
		thread = thread->next;
	};

	// when WNOHANG is clear
	while ((threadToKill == NULL) && ((flags & WNOHANG) == 0))
	{
		//currentThread->flags |= THREAD_WAITING;
		//currentThread->therrno = ECHILD;
		//*((int*)&regs->rax) = -1;
		//switchTask(regs);
		getCurrentThread()->flags |= THREAD_WAITING;
		unlockSched();
		kyield();
		if (getCurrentThread()->sigcnt > sigcnt)
		{
			ERRNO = EINTR;
			return -1;
		};
		lockSched();
	};

	unlockSched();
	ASM("sti");

	// when WNOHANG is set
	if (threadToKill == NULL)
	{
		currentThread->therrno = ECHILD;
		return -1;
	};

	// there is a process ready to be deleted, it's already removed from the runqueue.
	kfree(thread->stack);
	DownrefProcessMemory(thread->pm);
	ftabDownref(thread->ftab);

	if (thread->fpexec != NULL)
	{
		if (thread->fpexec->close != NULL) thread->fpexec->close(thread->fpexec);
		kfree(thread->fpexec);
	};

	if (thread->execPars != NULL) kfree(thread->execPars);
	int ret = thread->pid;
	kfree(thread);

	return ret;
};
Пример #4
0
static void ipreasmThread(void *ignore)
{
	// notice that we start in the waiting state, so as soon as we wake up,
	// scan the lists
	
	while (1)
	{
		spinlockAcquire(&reasmLock);
		//kprintf("REASSEMBLER TRIGGERED\n");
		
		if (firstFragList == NULL)
		{
			ASM("cli");
			reasmHandle->wakeTime = 0;
			reasmHandle->flags |= THREAD_WAITING;
			kyield();
		};
		
		IPFragmentList *list = firstFragList;
		int earliestDeadline = firstFragList->deadlineTicks;
		reasmHandle->wakeTime = 0;
		
		while (list != NULL)
		{
			if (getTicks() >= list->deadlineTicks)
			{
				// passed the deadline, just delete all fragments
				kprintf_debug("DEADLINE PASSED!\n");
				IPFragment *frag = list->fragList;
				while (frag != NULL)
				{
					kprintf("FRAGMENT: offset=%d, size=%d, last=%d\n", (int) frag->fragOffset, (int) frag->fragSize, frag->lastFragment);
					IPFragment *next = frag->next;
					kfree(frag);
					frag = next;
				};
				
				if (list == firstFragList)
				{
					firstFragList = list->next;
				};
				
				if (list == lastFragList)
				{
					lastFragList = list->prev;
				};
				
				if (list->prev != NULL) list->prev->next = list->next;
				if (list->next != NULL) list->next->prev = list->prev;
				IPFragmentList *nextList = list->next;
				kfree(list);
				list = nextList;
			}
			else
			{
				if (isFragmentListComplete(list))
				{
					size_t packetSize = calculatePacketSize(list);
					char *buffer = (char*) kmalloc(packetSize);
					
					IPFragment *frag = list->fragList;
					while (frag != NULL)
					{
						memcpy(&buffer[frag->fragOffset], frag->data, frag->fragSize);
						IPFragment *next = frag->next;
						kfree(frag);
						frag = next;
					};
					
					if (list->family == AF_INET)
					{
						struct sockaddr_in src;
						memset(&src, 0, sizeof(struct sockaddr_in));
						src.sin_family = AF_INET;
						memcpy(&src.sin_addr, list->srcaddr, 4);
						
						struct sockaddr_in dest;
						memset(&dest, 0, sizeof(struct sockaddr_in));
						dest.sin_family = AF_INET;
						memcpy(&dest.sin_addr, list->dstaddr, 4);
						
						onTransportPacket((struct sockaddr*)&src, (struct sockaddr*)&dest,
									sizeof(struct sockaddr_in), buffer, packetSize, list->proto);
					}
					else
					{
						struct sockaddr_in6 src;
						memset(&src, 0, sizeof(struct sockaddr_in6));
						src.sin6_family = AF_INET6;
						memcpy(&src.sin6_addr, list->srcaddr, 16);
						
						struct sockaddr_in6 dest;
						memset(&dest, 0, sizeof(struct sockaddr_in6));
						dest.sin6_family = AF_INET6;
						memcpy(&dest.sin6_addr, list->dstaddr, 16);
						
						onTransportPacket((struct sockaddr*) &src, (struct sockaddr*) &dest,
									sizeof(struct sockaddr_in6), buffer, packetSize, list->proto);
					};
					
					if (list == firstFragList)
					{
						firstFragList = list->next;
					};
				
					if (list == lastFragList)
					{
						lastFragList = list->prev;
					};
					
					if (list->prev != NULL) list->prev->next = list->next;
					if (list->next != NULL) list->next->prev = list->prev;
					IPFragmentList *nextList = list->next;
					kfree(list);
					list = nextList;
					
					kprintf_debug("IPREASM: reassembled fragmented packet of size %d\n", (int) packetSize);
					kfree(buffer);
				}
				else
				{
					if (list->deadlineTicks < earliestDeadline)
					{
						earliestDeadline = list->deadlineTicks;
					};
					
					list = list->next;
				};
			};
		};
		
		ASM("cli");
		reasmHandle->wakeTime = earliestDeadline;
		reasmHandle->flags |= THREAD_WAITING;
		spinlockRelease(&reasmLock);
		kyield();
	};
};