Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*$off*/
- /*$4 *******************************************************************************************************************
- *
- * DESCRIPTION: example to demonstrate how to call syscall
- *
- * AUTHOR: robert.berger@reliableembeddedsystems.com
- *
- * FILENAME: clock-nanoscleep.c
- *
- * REMARKS:
- *
- * HISTORY: 001a,13 Jul 2020,robert.berger written
- *
- * COPYRIGHT: (C) 2020
- *
- *********************************************************************************************************************** */
- /*$on*/
- /*
- #define my_syscall(a) syscall(__NR_my_syscall, a)
- 407 common clock_nanosleep_time64 sys_clock_nanosleep
- */
- /*
- from kernel: arch/arm/tools/syscall.tbl
- <num> <abi> <name> [<entry point> [<oabi compat entry point>]]
- #
- # Where abi is:
- # common - for system calls shared between oabi and eabi (may have compat)
- # oabi - for oabi-only system calls (may have compat)
- # eabi - for eabi-only system calls
- #
- # For each syscall number, "common" is mutually exclusive with oabi and eabi
- #
- 407 common clock_nanosleep_time64 sys_clock_nanosleep
- */
- /*
- from kernel: include/linux/syscalls.h
- asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
- const struct __kernel_timespec __user *rqtp,
- struct __kernel_timespec __user *rmtp);
- */
- /*
- from kernel config:
- config POSIX_TIMERS
- bool "Posix Clocks & timers" if EXPERT
- default y
- help
- This includes native support for POSIX timers to the kernel.
- Some embedded systems have no use for them and therefore they
- can be configured out to reduce the size of the kernel image.
- When this option is disabled, the following syscalls won't be
- available: timer_create, timer_gettime: timer_getoverrun,
- timer_settime, timer_delete, clock_adjtime, getitimer,
- setitimer, alarm. Furthermore, the clock_settime, clock_gettime,
- clock_getres and clock_nanosleep syscalls will be limited to
- CLOCK_REALTIME, CLOCK_MONOTONIC and CLOCK_BOOTTIME only.
- If unsure say y.
- */
- /*
- from glibc: https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/unix/sysv/linux/clock_nanosleep.c
- */
- /*$3 ===================================================================================================================
- $C Included headers
- ======================================================================================================================= */
- #define _GNU_SOURCE
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <sys/syscall.h>
- #include <unistd.h>
- #include <time.h>
- /*$3 ===================================================================================================================
- $C Constants
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Macros
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Types
- ======================================================================================================================= */
- #if __TIMESIZE == 64
- #define my__timespec64 timespec
- #else
- /* The glibc Y2038-proof struct __timespec64 structure for a time value.
- To keep things Posix-ish, we keep the nanoseconds field a 32-bit
- signed long, but since the Linux field is a 64-bit signed int, we
- pad our tv_nsec with a 32-bit unnamed bit-field padding.
- As a general rule the Linux kernel is ignoring upper 32 bits of
- tv_nsec field. */
- struct my__timespec64 {
- __time64_t tv_sec; /* Seconds */
- #if BYTE_ORDER == BIG_ENDIAN
- __int32_t:32; /* Padding */
- __int32_t tv_nsec; /* Nanoseconds */
- #else
- __int32_t tv_nsec; /* Nanoseconds */
- __int32_t:32; /* Padding */
- #endif
- };
- #endif
- /*$3 ===================================================================================================================
- $C Imported data
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Private data
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Public data
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Imported function declarations
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Public function declarations
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Private function declarations
- ======================================================================================================================= */
- /*$3 ===================================================================================================================
- $C Private function definitions
- ======================================================================================================================= */
- /* Convert a known valid struct timespec into a struct __timespec64. */
- static inline struct my__timespec64
- my_valid_timespec_to_timespec64(const struct timespec ts)
- {
- struct my__timespec64 ts64;
- ts64.tv_sec = ts.tv_sec;
- ts64.tv_nsec = ts.tv_nsec;
- return ts64;
- }
- /*$3 ===================================================================================================================
- $C Public function definitions
- ======================================================================================================================= */
- void my_sleep_ms(int millisec)
- {
- struct timespec res;
- res.tv_sec = millisec / 1000;
- res.tv_nsec = (millisec * 1000000) % 1000000000;
- clock_nanosleep(CLOCK_MONOTONIC, 0, &res, NULL);
- }
- void my_clock_nanosleep_time64(int millisec)
- {
- long rc;
- struct timespec res32;
- struct my__timespec64 res64;
- res32.tv_sec = millisec / 1000;
- res32.tv_nsec = (millisec * 1000000) % 1000000000;
- /*
- here we are set up to call
- clock_nanosleep(CLOCK_MONOTONIC, 0, &res32, NULL);
- but we don't call it
- */
- /* instead we prepare to call clock_nanosleep_time64 */
- res64 = my_valid_timespec_to_timespec64(res32);
- /* call clock_nanosleep_time64 directly via syscall */
- printf("--> before syscall\n");
- rc = syscall(__NR_clock_nanosleep_time64,
- CLOCK_MONOTONIC, 0, &res64, NULL);
- printf("<-- after syscall\n");
- /* check return value */
- printf("\nReturned my_syscall, rc = %ld\n", rc);
- if (rc < 0) {
- perror("syscall returned ");
- }
- }
- int main(int argc, char *argv[])
- {
- argc = argc;
- argv = argv;
- /* call clock_nanosleep
- which calls clock_nanosleep_time64 from glibc 2.30
- and if that fails falls back to clock_nansleep (old syscall) instead
- */
- my_sleep_ms(1);
- /* call clock_nanosleep_time64 directly via syscall
- This will fail e.g. on a 4.19 kernel which does not
- contain this syscall
- */
- my_clock_nanosleep_time64(1);
- exit(EXIT_SUCCESS);
- }
- /* EOF */
Add Comment
Please, Sign In to add comment