diff --git a/lib/libc/gen/exterr_cat_filenames.h b/lib/libc/gen/exterr_cat_filenames.h --- a/lib/libc/gen/exterr_cat_filenames.h +++ b/lib/libc/gen/exterr_cat_filenames.h @@ -11,6 +11,7 @@ [EXTERR_CAT_FILEDESC] = "kern/kern_descrip.c", [EXTERR_CAT_PROCEXIT] = "kern/kern_exit.c", [EXTERR_CAT_FORK] = "kern/kern_fork.c", + [EXTERR_CAT_TIME] = "kern/kern_time.c", [EXTERR_CAT_GENIO] = "kern/sys_generic.c", [EXTERR_CAT_VFSBIO] = "kern/vfs_bio.c", [EXTERR_CAT_INOTIFY] = "kern/vfs_inotify.c", diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -32,10 +32,12 @@ #include #include "opt_ktrace.h" +#define EXTERR_CATEGORY EXTERR_CAT_TIME #include #include #include #include +#include #include #include #include @@ -216,7 +218,7 @@ *clk_id = MAKE_THREAD_CPUCLOCK(tid); return (0); default: - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid CPUCLOCK_WHICH %jd", which)); } } @@ -300,14 +302,16 @@ tid = clock_id & CPUCLOCK_ID_MASK; td2 = tdfind(tid, p->p_pid); if (td2 == NULL) - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid thread id %jd", + (intmax_t)tid)); kern_thread_cputime(td2, ats); PROC_UNLOCK(td2->td_proc); } else { pid = clock_id & CPUCLOCK_ID_MASK; error = pget(pid, PGET_CANSEE, &p2); if (error != 0) - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid process id %jd", + (intmax_t)pid)); kern_process_cputime(p2, ats); PROC_UNLOCK(p2); } @@ -381,7 +385,8 @@ break; default: if ((int)clock_id >= 0) - return (EINVAL); + return (EXTERROR(EINVAL, "Unknown clock id %jd", + (intmax_t)clock_id)); return (get_cputime(td, clock_id, ats)); } return (0); @@ -419,13 +424,14 @@ if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) return (error); if (clock_id != CLOCK_REALTIME) - return (EINVAL); + return (EXTERROR(EINVAL, "clock_id %jd not CLOCK_REALTIME", + (intmax_t)clock_id)); if (!timespecvalid_interval(ats)) - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid timespec")); if (!allow_insane_settime && (ats->tv_sec > 8000ULL * 365 * 24 * 60 * 60 || ats->tv_sec < utc_offset())) - return (EINVAL); + return (EXTERROR(EINVAL, "Insane clock jump")); /* XXX Don't convert nsec->usec and back */ TIMESPEC_TO_TIMEVAL(&atv, ats); error = settime(td, &atv); @@ -493,7 +499,8 @@ default: if ((int)clock_id < 0) goto cputime; - return (EINVAL); + return (EXTERROR(EINVAL, "clock_id %jd invalid", + (intmax_t)clock_id)); } return (0); } @@ -523,9 +530,10 @@ bool is_abs_real, precise; if (rqt->tv_nsec < 0 || rqt->tv_nsec >= NS_PER_SEC) - return (EINVAL); + return (EXTERROR(EINVAL, "rqt bad nanosecond %jd", + (intmax_t)rqt->tv_nsec)); if ((flags & ~TIMER_ABSTIME) != 0) - return (EINVAL); + return (EXTERROR(EINVAL, "Bad timer flags set %#x", flags)); switch (clock_id) { case CLOCK_REALTIME: case CLOCK_TAI: @@ -562,7 +570,8 @@ return (ENOTSUP); case CLOCK_THREAD_CPUTIME_ID: default: - return (EINVAL); + return (EXTERROR(EINVAL, "clock_id %jd invalid", + (intmax_t)clock_id)); } do { ts = *rqt; @@ -743,7 +752,8 @@ if (tv) { if (tv->tv_usec < 0 || tv->tv_usec >= 1000000 || tv->tv_sec < 0) - return (EINVAL); + return (EXTERROR(EINVAL, "Bad timeval %jd %jd", + (intmax_t)tv->tv_sec, (intmax_t)tv->tv_usec)); error = settime(td, tv); } return (error); @@ -795,7 +805,7 @@ struct timeval ctv; if (which > ITIMER_PROF) - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid itimer type %u", which)); if (which == ITIMER_REAL) { /* @@ -863,19 +873,22 @@ return (kern_getitimer(td, which, oitv)); if (which > ITIMER_PROF) - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid itimer type %u", which)); #ifdef KTRACE if (KTRPOINT(td, KTR_STRUCT)) ktritimerval(aitv); #endif if (itimerfix(&aitv->it_value) || aitv->it_value.tv_sec > INT32_MAX / 2) - return (EINVAL); + return (EXTERROR(EINVAL, "Interval too large %jd", + (intmax_t)aitv->it_value.tv_sec)); if (!timevalisset(&aitv->it_value)) timevalclear(&aitv->it_interval); else if (itimerfix(&aitv->it_interval) || aitv->it_interval.tv_sec > INT32_MAX / 2) - return (EINVAL); + return (EXTERROR(EINVAL, + "Interval too large for existing timer %jd", + (intmax_t)aitv->it_interval.tv_sec)); if (which == ITIMER_REAL) { PROC_LOCK(p); @@ -1282,20 +1295,24 @@ int error; if (clock_id < 0 || clock_id >= MAX_CLOCKS) - return (EINVAL); + return (EXTERROR(EINVAL, "Invalid clock_id %jd", + (intmax_t)clock_id)); if (posix_clocks[clock_id].timer_create == NULL) - return (EINVAL); + return (EXTERROR(EINVAL, "Null posix clock %jd", + (intmax_t)clock_id)); if (evp != NULL) { if (evp->sigev_notify != SIGEV_NONE && evp->sigev_notify != SIGEV_SIGNAL && evp->sigev_notify != SIGEV_THREAD_ID) - return (EINVAL); + return (EXTERROR(EINVAL, "sigev_notify invalid %d", + evp->sigev_notify)); if ((evp->sigev_notify == SIGEV_SIGNAL || evp->sigev_notify == SIGEV_THREAD_ID) && !_SIG_VALID(evp->sigev_signo)) - return (EINVAL); + return (EXTERROR(EINVAL, "signal number invalid %d", + evp->sigev_notify)); } if (p->p_itimers == NULL) @@ -1420,7 +1437,7 @@ it = itimer_find(p, timerid); if (it == NULL) { PROC_UNLOCK(p); - return (EINVAL); + return (EXTERROR(EINVAL, "No itimer found id %d", timerid)); } PROC_UNLOCK(p); @@ -1478,7 +1495,7 @@ PROC_LOCK(p); if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { PROC_UNLOCK(p); - error = EINVAL; + error = EXTERROR(EINVAL, "No itimer found %d", timer_id); } else { PROC_UNLOCK(p); itimer_enter(it); @@ -1519,7 +1536,7 @@ PROC_LOCK(p); if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { PROC_UNLOCK(p); - error = EINVAL; + error = EXTERROR(EINVAL, "No itimer found %d", timer_id); } else { PROC_UNLOCK(p); itimer_enter(it); @@ -1553,7 +1570,7 @@ if (timer_id < 3 || (it = itimer_find(p, timer_id)) == NULL) { PROC_UNLOCK(p); - error = EINVAL; + error = EXTERROR(EINVAL, "No itimer found %d", timer_id); } else { td->td_retval[0] = it->it_overrun_last; ITIMER_UNLOCK(it); @@ -1625,11 +1642,11 @@ val = *value; if (itimespecfix(&val.it_value)) - return (EINVAL); + return (EXTERROR(EINVAL, "Cannot fix itimer")); if (timespecisset(&val.it_value)) { if (itimespecfix(&val.it_interval)) - return (EINVAL); + return (EXTERROR(EINVAL, "Cannot fix interval")); } else { timespecclear(&val.it_interval); } diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master --- a/sys/kern/syscalls.master +++ b/sys/kern/syscalls.master @@ -52,6 +52,7 @@ ; handler is declared or used. Handled in MD syscall code. ; CAPENABLED syscall is allowed in capability mode ; NORETURN the syscall does not return +; INTR the syscall can be interrupted and may need to be restarted. ; ; To support programmatic generation of both the default ABI and 32-bit compat ; (freebsd32) we impose a number of restrictions on the types of system calls. @@ -133,21 +134,21 @@ 2 AUE_FORK STD|CAPENABLED { int fork(void); } -3 AUE_READ STD|CAPENABLED { +3 AUE_READ STD|CAPENABLED|INTR { ssize_t read( int fd, _Out_writes_bytes_(nbyte) void *buf, size_t nbyte ); } -4 AUE_WRITE STD|CAPENABLED { +4 AUE_WRITE STD|CAPENABLED|INTR { ssize_t write( int fd, _In_reads_bytes_(nbyte) const void *buf, size_t nbyte ); } -5 AUE_OPEN_RWTC STD { +5 AUE_OPEN_RWTC STD|INTR { int open( _In_z_ const char *path, int flags, @@ -161,7 +162,7 @@ int fd ); } -7 AUE_WAIT4 STD|CAPENABLED { +7 AUE_WAIT4 STD|CAPENABLED|INTR { int wait4( int pid, _Out_opt_ int *status, @@ -286,7 +287,7 @@ int flags ); } -29 AUE_RECVFROM STD|CAPENABLED { +29 AUE_RECVFROM STD|CAPENABLED|INTR { ssize_t recvfrom( int s, _Out_writes_bytes_(len) void *buf, @@ -625,7 +626,7 @@ } ; XXX should be { int fcntl(int fd, int cmd, ...); } ; but we're not ready for varargs. -93 AUE_SELECT STD|CAPENABLED { +93 AUE_SELECT STD|CAPENABLED|INTR { int select( int nd, _Inout_opt_ fd_set *in, @@ -748,14 +749,14 @@ _Out_opt_ _Contains_ptr_ struct sigstack *oss ); } -113 AUE_RECVMSG COMPAT|CAPENABLED { +113 AUE_RECVMSG COMPAT|CAPENABLED|INTR { int recvmsg( int s, _Inout_ _Contains_ptr_ struct omsghdr *msg, int flags ); } -114 AUE_SENDMSG COMPAT|CAPENABLED { +114 AUE_SENDMSG COMPAT|CAPENABLED|INTR { int sendmsg( int s, _In_ _Contains_ptr_ const struct omsghdr *msg, @@ -785,14 +786,14 @@ ); } 119 AUE_NULL RESERVED -120 AUE_READV STD|CAPENABLED { +120 AUE_READV STD|CAPENABLED|INTR { ssize_t readv( int fd, _In_reads_(iovcnt) _Contains_long_ptr_ const struct iovec *iovp, u_int iovcnt ); } -121 AUE_WRITEV STD|CAPENABLED { +121 AUE_WRITEV STD|CAPENABLED|INTR { ssize_t writev( int fd, _In_reads_(iovcnt) _Contains_long_ptr_ const struct iovec *iovp, @@ -870,7 +871,7 @@ mode_t mode ); } -133 AUE_SENDTO STD|CAPENABLED { +133 AUE_SENDTO STD|CAPENABLED|INTR { ssize_t sendto( int s, _In_reads_bytes_(len) const void *buf, @@ -1084,7 +1085,7 @@ } ; XXX should be { int shmsys(int which, ...); } 172 AUE_NULL RESERVED -173 AUE_PREAD COMPAT6|CAPENABLED { +173 AUE_PREAD COMPAT6|CAPENABLED|INTR { ssize_t pread( int fd, _Out_writes_bytes_(nbyte) void *buf, @@ -1093,7 +1094,7 @@ off_t offset ); } -174 AUE_PWRITE COMPAT6|CAPENABLED { +174 AUE_PWRITE COMPAT6|CAPENABLED|INTR { ssize_t pwrite( int fd, _In_reads_bytes_(nbyte) const void *buf, @@ -1409,7 +1410,7 @@ int timerid ); } -240 AUE_NULL STD|CAPENABLED { +240 AUE_NULL STD|CAPENABLED|INTR { int nanosleep( _In_ _Contains_long_timet_ const struct timespec *rqtp, _Out_opt_ _Contains_long_timet_ struct timespec *rmtp @@ -1430,7 +1431,7 @@ _Out_ _Contains_timet_ struct ffclock_estimate *cest ); } -244 AUE_NULL STD { +244 AUE_NULL STD|INTR { int clock_nanosleep( clockid_t clock_id, int flags, @@ -1535,7 +1536,7 @@ ); } 281-288 AUE_NULL RESERVED -289 AUE_PREADV STD|CAPENABLED { +289 AUE_PREADV STD|CAPENABLED|INTR { ssize_t preadv( int fd, _In_reads_(iovcnt) _Contains_long_ptr_ struct iovec *iovp, @@ -1543,7 +1544,7 @@ off_t offset ); } -290 AUE_PWRITEV STD|CAPENABLED { +290 AUE_PWRITEV STD|CAPENABLED|INTR { ssize_t pwritev( int fd, _In_reads_(iovcnt) _Contains_long_ptr_ struct iovec *iovp, @@ -1936,7 +1937,7 @@ 362 AUE_KQUEUE STD|CAPENABLED { int kqueue(void); } -363 AUE_KEVENT COMPAT11|CAPENABLED { +363 AUE_KEVENT COMPAT11|CAPENABLED|INTR { int kevent( int fd, _In_reads_opt_(nchanges) _Contains_ptr_ const struct freebsd11_kevent *changelist, @@ -2349,7 +2350,7 @@ _In_opt_ _Contains_long_timet_ const struct timespec *abstime ); } -442 AUE_NULL STD|CAPENABLED { +442 AUE_NULL STD|CAPENABLED|INTR { int thr_suspend( _In_opt_ _Contains_long_timet_ const struct timespec *timeout ); @@ -2415,7 +2416,7 @@ _In_z_ const char *path ); } -454 AUE_NULL STD|CAPENABLED { +454 AUE_NULL STD|CAPENABLED_INTR { int _umtx_op( _Inout_ void *obj, int op, @@ -2728,7 +2729,7 @@ ); } ; XXX: see the comment for open -499 AUE_OPENAT_RWTC STD|CAPENABLED { +499 AUE_OPENAT_RWTC STD|CAPENABLED|INTR { int openat( int fd, _In_z_ const char *path, @@ -2859,7 +2860,7 @@ ); } 521 AUE_NULL RESERVED -522 AUE_SELECT STD|CAPENABLED { +522 AUE_SELECT STD|CAPENABLED|INTR { int pselect( int nd, _Inout_opt_ fd_set *in, @@ -2935,7 +2936,7 @@ int advice ); } -532 AUE_WAIT6 STD { +532 AUE_WAIT6 STD|INTR { int wait6( idtype_t idtype, id_t id, @@ -3028,7 +3029,7 @@ _In_opt_ void *data ); } -545 AUE_POLL STD|CAPENABLED { +545 AUE_POLL STD|CAPENABLED|INTR { int ppoll( _Inout_updates_(nfds) struct pollfd *fds, u_int nfds, @@ -3191,7 +3192,7 @@ int flag ); } -569 AUE_NULL STD|CAPENABLED { +569 AUE_NULL STD|CAPENABLED|INTR { ssize_t copy_file_range( int infd, _Inout_opt_ off_t *inoffp, diff --git a/sys/sys/exterr_cat.h b/sys/sys/exterr_cat.h --- a/sys/sys/exterr_cat.h +++ b/sys/sys/exterr_cat.h @@ -40,6 +40,7 @@ #define EXTERR_CAT_FORK 15 #define EXTERR_CAT_PROCEXIT 16 #define EXTERR_CAT_VMM 17 +#define EXTERR_CAT_TIME 18 #endif diff --git a/sys/tools/syscalls/core/syscall.lua b/sys/tools/syscalls/core/syscall.lua --- a/sys/tools/syscalls/core/syscall.lua +++ b/sys/tools/syscalls/core/syscall.lua @@ -31,6 +31,7 @@ "NORETURN", "NOTSTATIC", "SYSMUX", + "INTR" } -- Native is an arbitrarily large number to have a constant and not