Welcome to The Fiwix Project
A UNIX-like kernel for the i386 architecture
1 /* 2 * fiwix/kernel/syscalls/nanosleep.c 3 * 4 * Copyright 2018, Jordi Sanfeliu. All rights reserved. 5 * Distributed under the terms of the Fiwix License. 6 */ 7 8 #include <fiwix/asm.h> 9 #include <fiwix/fs.h> 10 #include <fiwix/time.h> 11 #include <fiwix/timer.h> 12 #include <fiwix/process.h> 13 #include <fiwix/sched.h> 14 #include <fiwix/sleep.h> 15 #include <fiwix/errno.h> 16 17 #ifdef __DEBUG__ 18 #include <fiwix/stdio.h> 19 #endif /*__DEBUG__ */ 20 21 int sys_nanosleep(const struct timespec *req, struct timespec *rem) 22 { 23 int errno; 24 long int nsec; 25 26 #ifdef __DEBUG__ 27 printk("(pid %d) sys_nanosleep(0x%08x, 0x%08x)\n", current->pid, (unsigned int)req, (unsigned int)rem); 28 #endif /*__DEBUG__ */ 29 30 if((errno = check_user_area(VERIFY_READ, req, sizeof(struct timespec)))) { 31 return errno; 32 } 33 if(req->tv_sec < 0 || req->tv_nsec >= 1000000000L || req->tv_nsec < 0) { 34 return -EINVAL; 35 } 36 37 /* 38 * Since the current maximum precision of the kernel is only 10ms, we 39 * need to convert any lower request to a minimum of 10ms, even knowing 40 * that this might increase the sleep a bit more than the requested. 41 */ 42 nsec = req->tv_nsec; 43 if(nsec < 10000000L) { 44 nsec *= 10; 45 } 46 47 current->timeout = (req->tv_sec * HZ) + (nsec * HZ / 1000000000L); 48 if(current->timeout) { 49 sleep(&sys_nanosleep, PROC_INTERRUPTIBLE); 50 if(current->timeout) { 51 if(rem) { 52 if((errno = check_user_area(VERIFY_WRITE, rem, sizeof(struct timespec)))) { 53 return errno; 54 } 55 rem->tv_sec = current->timeout / HZ; 56 rem->tv_nsec = (current->timeout % HZ) * 1000000000L / HZ; 57 } 58 return -EINTR; 59 } 60 } 61 return 0; 62 }