예제 #1
0
파일: time.c 프로젝트: madd-games/glidix
time_t time()
{
	spinlockAcquire(&timeLock);
	time_t out = currentTime + (time_t) (getUptime()-timeUpdateStamp)/1000;
	spinlockRelease(&timeLock);
	return out;
};
예제 #2
0
파일: main.c 프로젝트: osstudy/glidix
MODULE_INIT()
{
	kprintf("isofs: registering the ISO filesystem\n");
	spinlockRelease(&isoMountLock);
	registerFSDriver(&isoDriver);
	return 0;
};
예제 #3
0
파일: physmem.c 프로젝트: osstudy/glidix
void initPhysMem(uint64_t numPages, MultibootMemoryMap *mmap, uint64_t mmapEnd)
{
	frameStackPointer = 0;
	nextFrame = 0x400;
	numSystemFrames = numPages;

	while ((uint64_t)mmap < mmapEnd)
	{
		if (isUseableMemory(mmap))
		{
			if (isFrameInArea(mmap, 0x400))
			{
				break;
			};
		};

		mmap = (MultibootMemoryMap*) ((uint64_t) mmap + mmap->size + 4);
	};

	if ((uint64_t)mmap >= mmapEnd)
	{
		panic("no RAM addresses detected!");
	};

	memoryMap = mmap;
	memoryMapEnd = mmapEnd;
	spinlockRelease(&physmemLock);
};
예제 #4
0
파일: sched.c 프로젝트: osstudy/glidix
int canSched(Thread *thread)
{
	if (thread->wakeTime != 0)
	{
		uint64_t currentTime = (uint64_t) getTicks();
		//if (thread->pid == 1)
		//{
		//	kprintf("process %d, wakeTime=%d, now=%d\n", (int) thread->pid, (int) thread->wakeTime, (int) currentTime);
		//};
		//kprintf("TIME: %d; WAKEY: %d, FLAGS: %a\n", currentTime, thread->wakeTime, getFlagsRegister());
		if (currentTime >= thread->wakeTime)
		{
			//kprintf("WAKING UP\n");
			thread->wakeTime = 0;
			thread->flags &= ~THREAD_WAITING;
		};
	};

	if (thread->flags & THREAD_NOSCHED) return 0;
#if 0
	if (thread->pm != NULL)
	{
		if (spinlockTry(&thread->pm->lock))
		{
			return 0;
		};

		spinlockRelease(&thread->pm->lock);
	};
#endif

	return 1;
};
예제 #5
0
파일: physmem.c 프로젝트: osstudy/glidix
uint64_t phmAllocFrame()
{
	spinlockAcquire(&physmemLock);
	uint64_t out;
	if (frameStackPointer == 0)
	{
		uint64_t mmapStartFrame = memoryMap->baseAddr / 0x1000;
		uint64_t mmapNumFrames = memoryMap->len / 0x1000;
		uint64_t mmapEndFrame = mmapStartFrame + mmapNumFrames;

		if (mmapEndFrame == nextFrame)
		{
			loadNextMemory();
		};

		out = nextFrame;
		nextFrame++;
	}
	else
	{
		out = frameStack[--frameStackPointer];
	};

	spinlockRelease(&physmemLock);
	return out;
};
예제 #6
0
파일: physmem.c 프로젝트: osstudy/glidix
void phmFreeFrame(uint64_t frame)
{
	if (frame < 0x200) panic("attempted to free frame %d (below 2MB)", frame);

	spinlockAcquire(&physmemLock);
	frameStack[frameStackPointer++] = frame;
	spinlockRelease(&physmemLock);
};
예제 #7
0
파일: time.c 프로젝트: madd-games/glidix
void initRTC()
{
	spinlockRelease(&timeLock);
	KernelThreadParams rtcPars;
	memset(&rtcPars, 0, sizeof(KernelThreadParams));
	rtcPars.stackSize = 0x4000;
	rtcPars.name = "RTC reader daemon";
	CreateKernelThread(rtcThread, &rtcPars, NULL);
};
예제 #8
0
파일: ipreasm.c 프로젝트: osstudy/glidix
void ipreasmInit()
{
	spinlockRelease(&reasmLock);
	
	KernelThreadParams params;
	memset(&params, 0, sizeof(KernelThreadParams));
	params.stackSize = DEFAULT_STACK_SIZE;
	params.name = "IP Reassembler";
	params.flags = THREAD_WAITING;
	reasmHandle = CreateKernelThread(ipreasmThread, &params, NULL);
};
예제 #9
0
파일: main.c 프로젝트: osstudy/glidix
MODULE_FINI()
{
	spinlockAcquire(&isoMountLock);
	if (isoMountCount > 0)
	{
		spinlockRelease(&isoMountLock);
		return 1;
	};

	return 0;
};
예제 #10
0
파일: devfs.c 프로젝트: osstudy/glidix
void DeleteDevice(Device ptr)
{
	spinlockAcquire(&devfsLock);
	DeviceFile *dev = (DeviceFile*) ptr;
	if (dev->prev != NULL) dev->prev->next = dev->next;
	if (dev->next != NULL) dev->next->prev = dev->prev;
	if (dev->data != NULL) kfree(dev->data);
	spinlockRelease(&devfsLock);

	kfree(dev);
};
예제 #11
0
파일: time.c 프로젝트: madd-games/glidix
static void rtcThread(void *data)
{
	uint8_t second, minute, hour, day, month, year=0;
	uint8_t lastSecond, lastMinute, lastHour, lastDay, lastMonth, lastYear;
	uint8_t registerB;

	while (1)
	{
		do
		{
			lastYear = year;
			lastMonth = month;
			lastDay = day;
			lastHour = hour;
			lastMinute = minute;
			lastSecond = second;

			while (getUpdateInProgress());
			second = getRTCRegister(0);
			minute = getRTCRegister(2);
			hour = getRTCRegister(4);
			day = getRTCRegister(7);
			month = getRTCRegister(8);
			year = getRTCRegister(9);
		} while ((second != lastSecond) || (minute != lastMinute) || (hour != lastHour)
			|| (month != lastMonth) || (year != lastYear) || (day != lastDay));

		registerB = getRTCRegister(0x0B);
		if (!(registerB & 0x04))
		{
			second = (second & 0xF) + (second / 16) * 10;
			minute = (minute & 0xF) + (minute / 16) * 10;
			hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80);
			day = (day & 0xF) + (day / 16) * 10;
			month = (month & 0xF) + (month / 16) * 10;
			year = (year & 0xF) + (year / 16) * 10;
		};

		if (!(registerB & 0x02) && (hour & 0x80))
		{
			hour = ((hour & 0x7F) + 12) % 24;
		};

		spinlockAcquire(&timeLock);
		currentTime = makeUnixTime(2000+year, month, day, hour, minute, second);
		timeUpdateStamp = getUptime();
		spinlockRelease(&timeLock);
		
		sleep(RTC_UPDATE_INTERVAL);
	};
};
예제 #12
0
파일: devfs.c 프로젝트: osstudy/glidix
void initDevfs()
{
	spinlockRelease(&devfsLock);
	devfs = (FileSystem*) kmalloc(sizeof(FileSystem));
	memset(devfs, 0, sizeof(FileSystem));
	devfs->fsname = "devfs";
	devfs->openroot = openroot;

	strcpy(nullDevice.name, "null");
	nullDevice.data = NULL;
	nullDevice.open = openNullDevice;
	nullDevice.prev = NULL;
	nullDevice.next = NULL;
};
예제 #13
0
파일: sched.c 프로젝트: osstudy/glidix
void switchTask(Regs *regs)
{
	ASM("sti");
	if (currentThread == NULL)
	{
		apic->timerInitCount = quantumTicks;
		return;
	};
	if (spinlockTry(&schedLock))
	{
		//kprintf_debug("WARNING: SCHED LOCKED\n");
		apic->timerInitCount = quantumTicks;
		return;
	};

	__sync_fetch_and_add(&switchTaskCounter, 1);

	// remember the context of this thread.
	fpuSave(&currentThread->fpuRegs);
	memcpy(&currentThread->regs, regs, sizeof(Regs));

	// get the next thread
	do
	{
		currentThread = currentThread->next;
	} while (!canSched(currentThread));

	// if there are signals waiting, and not currently being handled, then handle them.
	if (((currentThread->flags & THREAD_SIGNALLED) == 0) && (currentThread->sigcnt != 0))
	{
		// if the syscall is interruptable, do the switch-back.
		if (currentThread->flags & THREAD_INT_SYSCALL)
		{
			//kprintf_debug("signal in queue, THREAD_INT_SYSCALL ok\n");
			memcpy(&currentThread->regs, &currentThread->intSyscallRegs, sizeof(Regs));
			*((int64_t*)&currentThread->regs.rax) = -1;
			currentThread->therrno = EINTR;
		};
		
		// i've found that catching signals in kernel mode is a bad idea
		if ((currentThread->regs.cs & 3) == 3)
		{
			dispatchSignal(currentThread);
		};
	};

	spinlockRelease(&schedLock);
	jumpToTask();
};
예제 #14
0
파일: pipe.c 프로젝트: osstudy/glidix
int sys_pipe(int *pipefd)
{
	int rfd=-1, wfd=-1;

	FileTable *ftab = getCurrentThread()->ftab;
	spinlockAcquire(&ftab->spinlock);

	int i;
	for (i=0; i<MAX_OPEN_FILES; i++)
	{
		if (ftab->entries[i] == NULL)
		{
			if (rfd == -1)
			{
				rfd = i;
			}
			else if (wfd == -1)
			{
				wfd = i;
				break;
			};
		};
	};

	if ((rfd == -1) || (wfd == -1))
	{
		getCurrentThread()->therrno = EMFILE;
		return -1;
	};

	Pipe *pipe = (Pipe*) kmalloc(sizeof(Pipe));
	semInit(&pipe->sem);
	pipe->readcount = 0;
	pipe->writecount = 0;
	pipe->offRead = 0;
	pipe->offWrite = 0;
	pipe->size = 0;

	ftab->entries[rfd] = openPipe(pipe, O_RDONLY);
	ftab->entries[wfd] = openPipe(pipe, O_WRONLY);

	pipefd[0] = rfd;
	pipefd[1] = wfd;

	spinlockRelease(&ftab->spinlock);
	return 0;
};
예제 #15
0
파일: main.c 프로젝트: osstudy/glidix
static int iso_unmount(FileSystem *fs)
{
	ISOFileSystem *isofs = (ISOFileSystem*) fs->fsdata;
	semWait(&isofs->sem);
	if (isofs->numOpenInodes != 0)
	{
		kprintf_debug("isofs: cannot unmount because %d inodes are open\n", isofs->numOpenInodes);
		semSignal(&isofs->sem);
		return -1;
	};

	vfsClose(isofs->fp);
	kfree(isofs);

	spinlockAcquire(&isoMountLock);
	isoMountCount--;
	spinlockRelease(&isoMountLock);

	return 0;
};
예제 #16
0
파일: devfs.c 프로젝트: osstudy/glidix
Device AddDevice(const char *name, void *data, int (*open)(void*, File*, size_t), int flags)
{
	if (strlen(name) > 15)
	{
		return NULL;
	};

	DeviceFile *dev = (DeviceFile*) kmalloc(sizeof(DeviceFile));
	strcpy(dev->name, name);
	dev->data = data;
	dev->open = open;
	dev->prev = NULL;
	dev->next = NULL;

	spinlockAcquire(&devfsLock);
	DeviceFile *last = &nullDevice;
	while (last->next != NULL) last = last->next;
	last->next = dev;
	dev->prev = last;
	spinlockRelease(&devfsLock);

	return dev;
};
예제 #17
0
파일: elf64.c 프로젝트: osstudy/glidix
int elfExec(Regs *regs, const char *path, const char *pars, size_t parsz)
{
	//getCurrentThread()->therrno = ENOEXEC;

	vfsLockCreation();
	struct stat st;
	int error = vfsStat(path, &st);
	if (error != 0)
	{
		vfsUnlockCreation();
		return sysOpenErrno(error);
	};

	if (!vfsCanCurrentThread(&st, 1))
	{
		vfsUnlockCreation();
		getCurrentThread()->therrno = EPERM;
		return -1;
	};

	File *fp = vfsOpen(path, VFS_CHECK_ACCESS, &error);
	if (fp == NULL)
	{
		vfsUnlockCreation();
		return sysOpenErrno(error);
	};
	vfsUnlockCreation();

	if (fp->seek == NULL)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = EIO;
		return -1;
	};

	if (fp->dup == NULL)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = EIO;
		return -1;
	};

	Elf64_Ehdr elfHeader;
	if (vfsRead(fp, &elfHeader, sizeof(Elf64_Ehdr)) < sizeof(Elf64_Ehdr))
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	if (memcmp(elfHeader.e_ident, "\x7f" "ELF", 4) != 0)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	if (elfHeader.e_ident[EI_CLASS] != ELFCLASS64)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	if (elfHeader.e_ident[EI_DATA] != ELFDATA2LSB)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	if (elfHeader.e_ident[EI_VERSION] != 1)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	if (elfHeader.e_type != ET_EXEC)
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	if (elfHeader.e_phentsize < sizeof(Elf64_Phdr))
	{
		vfsClose(fp);
		getCurrentThread()->therrno = ENOEXEC;
		return -1;
	};

	ProgramSegment *segments = (ProgramSegment*) kmalloc(sizeof(ProgramSegment)*(elfHeader.e_phnum));
	memset(segments, 0, sizeof(ProgramSegment) * elfHeader.e_phnum);

	int interpNeeded = 0;
	Elf64_Dyn *dynamic;

	unsigned int i;
	for (i=0; i<elfHeader.e_phnum; i++)
	{
		fp->seek(fp, elfHeader.e_phoff + i * elfHeader.e_phentsize, SEEK_SET);
		Elf64_Phdr proghead;
		if (vfsRead(fp, &proghead, sizeof(Elf64_Phdr)) < sizeof(Elf64_Phdr))
		{
			kfree(segments);
			getCurrentThread()->therrno = ENOEXEC;
			return -1;
		};

		if (proghead.p_type == PT_PHDR)
		{
			continue;
		}
		else if (proghead.p_type == PT_NULL)
		{
			continue;
		}
		else if (proghead.p_type == PT_LOAD)
		{
			if (proghead.p_vaddr < 0x1000)
			{
				vfsClose(fp);
				kfree(segments);
				getCurrentThread()->therrno = ENOEXEC;
				return -1;
			};

			if ((proghead.p_vaddr+proghead.p_memsz) > 0x8000000000)
			{
				vfsClose(fp);
				kfree(segments);
				return -1;
			};

			uint64_t start = proghead.p_vaddr;
			segments[i].index = (start)/0x1000;

			uint64_t end = proghead.p_vaddr + proghead.p_memsz;
			uint64_t size = end - start;
			uint64_t numPages = ((start + size) / 0x1000) - segments[i].index + 1; 
			//if (size % 0x1000) numPages++;

			segments[i].count = (int) numPages;
			segments[i].fileOffset = proghead.p_offset;
			segments[i].memorySize = proghead.p_memsz;
			segments[i].fileSize = proghead.p_filesz;
			segments[i].loadAddr = proghead.p_vaddr;
			segments[i].flags = 0;

			if (proghead.p_flags & PF_R)
			{
				segments[i].flags |= PROT_READ;
			};

			if (proghead.p_flags & PF_W)
			{
				segments[i].flags |= PROT_WRITE;
			};

			if (proghead.p_flags & PF_X)
			{
				segments[i].flags |= PROT_EXEC;
			};
		}
		else if (proghead.p_type == PT_INTERP)
		{
			interpNeeded = 1;
		}
		else if (proghead.p_type == PT_DYNAMIC)
		{
			dynamic = (Elf64_Dyn*) proghead.p_vaddr;
		}
		else
		{
			kfree(segments);
			getCurrentThread()->therrno = ENOEXEC;
			return -1;
		};
	};

	// set the signal handler to default.
	getCurrentThread()->rootSigHandler = 0;

	// thread name
	strcpy(getCurrentThread()->name, path);

	// set the execPars
	Thread *thread = getCurrentThread();
	if (thread->execPars != NULL) kfree(thread->execPars);
	thread->execPars = (char*) kmalloc(parsz);
	thread->szExecPars = parsz;
	memcpy(thread->execPars, pars, parsz);

	// create a new address space
	ProcMem *pm = CreateProcessMemory();

	// switch the address space, so that AddSegment() can optimize mapping
	lockSched();
	ProcMem *oldPM = thread->pm;
	thread->pm = pm;
	unlockSched();
	SetProcessMemory(pm);
	DownrefProcessMemory(oldPM);

	// pass 1: allocate the frames and map them
	for (i=0; i<(elfHeader.e_phnum); i++)
	{
		if (segments[i].count > 0)
		{
			FrameList *fl = palloc_later(segments[i].count, segments[i].fileOffset, segments[i].fileSize);
			if (AddSegment(pm, segments[i].index, fl, segments[i].flags) != 0)
			{
				getCurrentThread()->therrno = ENOEXEC;
				pdownref(fl);
				DownrefProcessMemory(pm);
				break;
			};
			pdownref(fl);
		};
	};

	// change the fpexec
	if (thread->fpexec != NULL)
	{
		if (thread->fpexec->close != NULL) thread->fpexec->close(thread->fpexec);
		kfree(thread->fpexec);
	};
	thread->fpexec = fp;

	// make sure we jump to the entry upon return
	regs->rip = elfHeader.e_entry;

	// the errnoptr is now invalid
	thread->errnoptr = NULL;

	// close all files marked with O_CLOEXEC (on glidx a.k.a. FD_CLOEXEC)
	spinlockAcquire(&getCurrentThread()->ftab->spinlock);
	for (i=0; i<MAX_OPEN_FILES; i++)
	{
		File *fp = getCurrentThread()->ftab->entries[i];
		if (fp != NULL)
		{
			if (fp->oflag & O_CLOEXEC)
			{
				getCurrentThread()->ftab->entries[i] = NULL;
				vfsClose(fp);
			};
		};
	};
	spinlockRelease(&getCurrentThread()->ftab->spinlock);
	
	// suid/sgid stuff
	if (st.st_mode & VFS_MODE_SETUID)
	{
		thread->euid = st.st_uid;
		//thread->ruid = st.st_uid;
		//thread->suid = st.st_uid;
		thread->flags |= THREAD_REBEL;
	};

	if (st.st_mode & VFS_MODE_SETGID)
	{
		thread->egid = st.st_gid;
		//thread->rgid = st.st_gid;
		//thread->sgid = st.st_gid;
		thread->flags |= THREAD_REBEL;
	};

	if (interpNeeded)
	{
		linkInterp(regs, dynamic, pm);
	};

	return 0;
};
예제 #18
0
파일: sched.c 프로젝트: osstudy/glidix
int threadClone(Regs *regs, int flags, MachineState *state)
{
	Thread *thread = (Thread*) kmalloc(sizeof(Thread));
	fpuSave(&thread->fpuRegs);
	memcpy(&thread->regs, regs, sizeof(Regs));
	thread->regs.rax = 0;

	if (state != NULL)
	{
		memcpy(&thread->fpuRegs, &state->fpuRegs, 512);
		thread->regs.rdi = state->rdi;
		thread->regs.rsi = state->rsi;
		thread->regs.rbp = state->rbp;
		thread->regs.rbx = state->rbx;
		thread->regs.rdx = state->rdx;
		thread->regs.rcx = state->rcx;
		thread->regs.rax = state->rax;
		thread->regs.r8  = state->r8 ;
		thread->regs.r9  = state->r9 ;
		thread->regs.r10 = state->r10;
		thread->regs.r11 = state->r11;
		thread->regs.r12 = state->r12;
		thread->regs.r13 = state->r13;
		thread->regs.r14 = state->r14;
		thread->regs.r15 = state->r15;
		thread->regs.rip = state->rip;
		thread->regs.rsp = state->rsp;
	};

	// kernel stack
	thread->stack = kmalloc(DEFAULT_STACK_SIZE);
	thread->stackSize = DEFAULT_STACK_SIZE;

	strcpy(thread->name, currentThread->name);
	thread->flags = 0;

	// process memory
	if (flags & CLONE_SHARE_MEMORY)
	{
		UprefProcessMemory(currentThread->pm);
		thread->pm = currentThread->pm;
	}
	else
	{
		if (currentThread->pm != NULL)
		{
			thread->pm = DuplicateProcessMemory(currentThread->pm);
		}
		else
		{
			thread->pm = CreateProcessMemory();
		};
	};

	// assign pid
	spinlockAcquire(&schedLock);
	thread->pid = nextPid++;
	spinlockRelease(&schedLock);

	// remember parent pid
	thread->pidParent = currentThread->pid;

	// file table
	if (flags & CLONE_SHARE_FTAB)
	{
		ftabUpref(currentThread->ftab);
		thread->ftab = currentThread->ftab;
	}
	else
	{
		if (currentThread->ftab != NULL)
		{
			thread->ftab = ftabDup(currentThread->ftab);
		}
		else
		{
			thread->ftab = ftabCreate();
		};
	};

	// inherit UIDs/GIDs from the parent
	thread->euid = currentThread->euid;
	thread->suid = currentThread->suid;
	thread->ruid = currentThread->ruid;
	thread->egid = currentThread->egid;
	thread->sgid = currentThread->sgid;
	thread->rgid = currentThread->rgid;

	// inherit the working directory
	strcpy(thread->cwd, currentThread->cwd);

	// duplicate the executable description.
	if (currentThread->fpexec == NULL)
	{
		thread->fpexec = NULL;
	}
	else
	{
		File *fpexec = (File*) kmalloc(sizeof(File));
		memset(fpexec, 0, sizeof(File));
		currentThread->fpexec->dup(currentThread->fpexec, fpexec, sizeof(File));
		thread->fpexec = fpexec;
	};
	
	// inherit the root signal handler
	thread->rootSigHandler = currentThread->rootSigHandler;

	// empty signal queue
	thread->sigput = 0;
	thread->sigfetch = 0;
	thread->sigcnt = 0;

	// exec params
	if (currentThread->pid != 0)
	{
		thread->execPars = (char*) kmalloc(currentThread->szExecPars);
		memcpy(thread->execPars, currentThread->execPars, currentThread->szExecPars);
		thread->szExecPars = currentThread->szExecPars;
	}
	else
	{
		thread->execPars = NULL;
		thread->szExecPars = 0;
	};

	thread->therrno = 0;
	thread->wakeTime = 0;
	thread->umask = 0;

	memcpy(thread->groups, currentThread->groups, sizeof(gid_t)*16);
	thread->numGroups = currentThread->numGroups;
	
	// if the address space is shared, the errnoptr is now invalid;
	// otherwise, it can just stay where it is.
	if (flags & CLONE_SHARE_MEMORY)
	{
		thread->errnoptr = NULL;
	}
	else
	{
		thread->errnoptr = currentThread->errnoptr;
	};

	// link into the runqueue
	spinlockAcquire(&schedLock);
	currentThread->next->prev = thread;
	thread->next = currentThread->next;
	thread->prev = currentThread;
	currentThread->next = thread;
	spinlockRelease(&schedLock);

	return thread->pid;
};
예제 #19
0
파일: sched.c 프로젝트: osstudy/glidix
Thread* CreateKernelThread(KernelThreadEntry entry, KernelThreadParams *params, void *data)
{
	// params
	uint64_t stackSize = DEFAULT_STACK_SIZE;
	if (params != NULL)
	{
		if (params->stackSize != 0) stackSize = params->stackSize;
	};
	const char *name = "Nameless thread";
	if (params != NULL)
	{
		if (params->name != NULL) name = params->name;
	};
	int threadFlags = 0;
	if (params != NULL)
	{
		threadFlags = params->flags;
	};

	// allocate and fill in the thread structure
	Thread *thread = (Thread*) kmalloc(sizeof(Thread));
	thread->stack = kmalloc(stackSize);
	thread->stackSize = stackSize;

	memset(&thread->fpuRegs, 0, 512);
	memset(&thread->regs, 0, sizeof(Regs));
	thread->regs.rip = (uint64_t) entry;
	thread->regs.rsp = ((uint64_t) thread->stack + thread->stackSize - 8) & ~0xF;	// -8 because we'll push the return address...
	thread->regs.cs = 8;
	thread->regs.ds = 16;
	thread->regs.ss = 0;
	thread->regs.rflags = getFlagsRegister() | (1 << 9);				// enable interrupts in that thread
	strcpy(thread->name, name);
	thread->flags = threadFlags;
	thread->pm = NULL;
	thread->pid = 0;
	thread->pidParent = 0;
	thread->ftab = NULL;
	thread->rootSigHandler = 0;
	thread->sigput = 0;
	thread->sigfetch = 0;
	thread->sigcnt = 0;

	// kernel threads always run as root
	thread->euid = 0;
	thread->suid = 0;
	thread->ruid = 0;
	thread->egid = 0;
	thread->sgid = 0;
	thread->rgid = 0;

	// start all kernel threads in "/initrd"
	strcpy(thread->cwd, "/initrd");

	// no executable attached
	thread->fpexec = NULL;

	// no errnoptr
	thread->errnoptr = NULL;

	// do not wake
	thread->wakeTime = 0;

	// no umask
	thread->umask = 0;

	// this will simulate a call from kernelThreadExit() to "entry()"
	// this is so that when entry() returns, the thread can safely exit.
	thread->regs.rdi = (uint64_t) data;
	*((uint64_t*)thread->regs.rsp) = (uint64_t) &kernelThreadExit;

	// link into the runqueue
	spinlockAcquire(&schedLock);
	currentThread->next->prev = thread;
	thread->next = currentThread->next;
	thread->prev = currentThread;
	currentThread->next = thread;
	// there is no need to update currentThread->prev, it will only be broken for the init
	// thread, which never exits, and therefore its prev will never need to be valid.
	spinlockRelease(&schedLock);
	
	return thread;
};
예제 #20
0
파일: devfs.c 프로젝트: osstudy/glidix
static void close(Dir *dir)
{
	spinlockRelease(&devfsLock);
};
예제 #21
0
파일: sched.c 프로젝트: osstudy/glidix
void unlockSched()
{
	spinlockRelease(&schedLock);
};
예제 #22
0
파일: sched.c 프로젝트: osstudy/glidix
void initSched()
{
	nextPid = 1;
	spinlockRelease(&schedLock);

	// create a new stack for this initial process
	firstThread.stack = kmalloc(DEFAULT_STACK_SIZE);
	firstThread.stackSize = DEFAULT_STACK_SIZE;

	// the value of registers do not matter except RSP and RIP,
	// also the startup function should never return.
	memset(&firstThread.fpuRegs, 0, 512);
	memset(&firstThread.regs, 0, sizeof(Regs));
	firstThread.regs.rip = (uint64_t) &startupThread;
	firstThread.regs.rsp = (uint64_t) firstThread.stack + firstThread.stackSize;
	firstThread.regs.cs = 8;
	firstThread.regs.ds = 16;
	firstThread.regs.ss = 0;
	firstThread.regs.rflags = getFlagsRegister() | (1 << 9);		// enable interrupts

	// other stuff
	strcpy(firstThread.name, "Startup thread");
	firstThread.flags = 0;
	firstThread.pm = NULL;
	firstThread.pid = 0;
	firstThread.ftab = NULL;
	firstThread.rootSigHandler = 0;
	firstThread.sigput = 0;
	firstThread.sigfetch = 0;
	firstThread.sigcnt = 0;

	// UID/GID stuff
	firstThread.euid = 0;
	firstThread.suid = 0;
	firstThread.ruid = 0;
	firstThread.egid = 0;
	firstThread.sgid = 0;
	firstThread.rgid = 0;

	// set the working directory to /initrd by default.
	strcpy(firstThread.cwd, "/initrd");

	// no executable
	firstThread.fpexec = NULL;

	// no error ptr
	firstThread.errnoptr = NULL;

	// no wakeing
	firstThread.wakeTime = 0;

	// no umask
	firstThread.umask = 0;

	// no supplementary groups
	firstThread.numGroups = 0;
	
	// linking
	firstThread.prev = &firstThread;
	firstThread.next = &firstThread;

	// switch to this new thread's context
	currentThread = &firstThread;
	apic->timerInitCount = quantumTicks;
	switchContext(&firstThread.regs);
};
예제 #23
0
파일: ipreasm.c 프로젝트: osstudy/glidix
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();
	};
};
예제 #24
0
파일: ipreasm.c 프로젝트: osstudy/glidix
void ipreasmPass(int family, char *srcaddr, char *dstaddr, int proto, uint32_t id, uint32_t fragOff, char *data, size_t fragSize, int moreFrags)
{
	spinlockAcquire(&reasmLock);
	
	int found = 0;
	
	IPFragmentList *list;
	for (list=firstFragList; list!=NULL; list=list->next)
	{
		if (isMatchingFragmentList(list, family, srcaddr, dstaddr, id))
		{
			if (list->proto != proto)
			{
				// ignore this packet because it's faulty
				kprintf_debug("OVERLAP\n");
				spinlockRelease(&reasmLock);
				return;
			};
			
			// see if this fragment is supposed to come before any that have so far arrived
			if (list->fragList->fragOffset > fragOff)
			{
				if (fragOff+fragSize > list->fragList->fragOffset)
				{
					// overlaps, reject
					kprintf_debug("OVERLAP\n");
					spinlockRelease(&reasmLock);
					return;
				};
				
				IPFragment *frag = NEW_EX(IPFragment, fragSize);
				frag->lastFragment = !moreFrags;
				frag->fragOffset = fragOff;
				frag->fragSize = fragSize;
				frag->prev = NULL;
				list->fragList->prev = frag;
				frag->next = list->fragList;
				memcpy(frag->data, data, fragSize);
				list->fragList = frag;
			}
			else
			{
				//kprintf_debug("here though\n");
				// find where to place this fragment
				IPFragment *scan = list->fragList;
				while (scan != NULL)
				{
					if (scan->fragOffset == fragOff)
					{
						// duplicate; reject
						kprintf_debug("OVERLAP\n");
						spinlockRelease(&reasmLock);
						return;
					};
				
					int doit = 0;
					if (scan->next == NULL)
					{
						if (fragOff > scan->fragOffset)
						{
							if (scan->fragOffset+scan->fragSize > fragOff)
							{
								// overlaps
								kprintf_debug("OVERLAP\n");
								spinlockRelease(&reasmLock);
								return;
							};
						
							doit = 1;
						};
					}
					else
					{
						if ((scan->fragOffset < fragOff) && (scan->next->fragOffset > fragOff))
						{
							// reject this packet if it is overlapping
							if (scan->fragOffset+scan->fragSize > fragOff)
							{
								// overlaps previous fragment
								kprintf_debug("OVERLAP\n");
								spinlockRelease(&reasmLock);
								return;
							};
						
							if (fragOff+fragSize > scan->next->fragOffset)
							{
								// overlaps next fragment
								kprintf_debug("OVERLAP\n");
								spinlockRelease(&reasmLock);
								return;
							};
						
							doit = 1;
						};
					};
				
					if (doit)
					{
						// OK, we can finally place the fragment
						IPFragment *frag = NEW_EX(IPFragment, fragSize);
						frag->lastFragment = !moreFrags;
						frag->fragOffset = fragOff;
						frag->fragSize = fragSize;
						frag->prev = scan;
						frag->next = scan->next;
						if (scan->next != NULL) scan->next->prev = frag;
						scan->next = frag;
						memcpy(frag->data, data, fragSize);
						break;
					}
					else
					{
						scan = scan->next;
					};
				};
			};
			
			found = 1;
		};
	};
	
	if (!found)
	{
		// create a new fragment list
		IPFragment *frag = NEW_EX(IPFragment, fragSize);
		frag->lastFragment = !moreFrags;
		frag->fragOffset = fragOff;
		frag->fragSize = fragSize;
		frag->prev = frag->next = NULL;
		memcpy(frag->data, data, fragSize);
		
		IPFragmentList *list = NEW(IPFragmentList);
		list->family = family;
		list->deadlineTicks = getTicks() + 60000;		// deadline after 60 seconds
		memcpy(list->srcaddr, srcaddr, 16);
		memcpy(list->dstaddr, dstaddr, 16);
		list->id = id;
		list->proto = proto;
		list->fragList = frag;
		
		if (firstFragList == NULL)
		{
			firstFragList = lastFragList = list;
			list->prev = list->next = NULL;
		}
		else
		{
			lastFragList->next = list;
			list->next = NULL;
			list->prev = lastFragList;
			lastFragList = list;
		};
	};
	
	signalThread(reasmHandle);
	spinlockRelease(&reasmLock);
};
예제 #25
0
파일: main.c 프로젝트: osstudy/glidix
static int isoMount(const char *image, FileSystem *fs, size_t szfs)
{
	spinlockAcquire(&isoMountLock);

	int error;
	File *fp = vfsOpen(image, 0, &error);
	if (fp == NULL)
	{
		spinlockRelease(&isoMountLock);
		kprintf_debug("isofs: could not open %s\n", image);
		return -1;
	};

	if (fp->seek == NULL)
	{
		spinlockRelease(&isoMountLock);
		kprintf_debug("isofs: %s cannot seek\n", image);
		vfsClose(fp);
		return -1;
	};

	fp->seek(fp, 0x8000, SEEK_SET);
	ISOPrimaryVolumeDescriptor primary;
	if (vfsRead(fp, &primary, sizeof(ISOPrimaryVolumeDescriptor)) != sizeof(ISOPrimaryVolumeDescriptor))
	{
		spinlockRelease(&isoMountLock);
		kprintf_debug("isofs: cannot read the whole ISOPrimaryVolumeDescriptor (EOF)\n");
		vfsClose(fp);
		return -1;
	};

	if (!checkPVD(&primary))
	{
		spinlockRelease(&isoMountLock);
		kprintf_debug("isofs: the Primary Volume Descriptor is invalid\n");
		vfsClose(fp);
		return -1;
	};

	kprintf_debug("isofs: PVD validated\n");

	ISOFileSystem *isofs = (ISOFileSystem*) kmalloc(sizeof(ISOFileSystem));
	isofs->fp = fp;
	semInit(&isofs->sem);

	ISODirentHeader *rootDir = (ISODirentHeader*) &primary.rootDir;
	isofs->rootStart = (uint64_t)rootDir->startLBA * (uint64_t)primary.blockSize;
	isofs->rootEnd = isofs->rootStart + (uint64_t)rootDir->fileSize;
	isofs->blockSize = (uint64_t)primary.blockSize;
	isofs->numOpenInodes = 0;

	kprintf_debug("isofs: root directory start LBA is %a, block size is %d\n", rootDir->startLBA, primary.blockSize);

	fs->fsdata = isofs;
	fs->fsname = "isofs";
	fs->openroot = iso_openroot;
	fs->unmount = iso_unmount;

	isoMountCount++;
	spinlockRelease(&isoMountLock);
	return 0;
};