C portable/cross-platform periodic timer (with millisecond resolution)? - c

I have been reading Signal Handler in a separate pthread using timer_create, and I decided to try implementing a C example for a periodic timer function based on the discussion there, and compiling it under MINGW64 for Windows.
It turns out, while MINGW64 can indeed emulate some aspects of POSIX under Windows, timer_create and sigevent are not part of that (/mingw64/include/signal.h does not contain declaration for sigevent - while MSYS2 /usr/include/signal.h, via /usr/include/sys/signal.h, does) - I get these errors:
test.c:153:1: error: unknown type name 'timer_t'; did you mean 'time_t'?
553 | timer_t timerId = 0;
| ^~~~~~~
| time_t
test.c: In function 'init_timer':
test.c:160:10: error: variable 'sev' has initializer but incomplete type
560 | struct sigevent sev = { 0 };
| ^~~~~~~~
test.c:160:27: warning: excess elements in struct initializer
560 | struct sigevent sev = { 0 };
| ^
test.c:160:27: note: (near initialization for 'sev')
test.c:160:19: error: storage size of 'sev' isn't known
560 | struct sigevent sev = { 0 };
| ^~~
test.c:170:22: error: 'SIGEV_THREAD' undeclared (first use in this function)
570 | sev.sigev_notify = SIGEV_THREAD;
| ^~~~~~~~~~~~
test.c:170:22: note: each undeclared identifier is reported only once for each function it appears in
test.c:174:9: warning: implicit declaration of function 'timer_create'; did you mean 'timerclear'? [-Wimplicit-function-declaration]
574 | res = timer_create(CLOCK_REALTIME, &sev, &timerId);
| ^~~~~~~~~~~~
| timerclear
test.c:180:9: warning: implicit declaration of function 'timer_settime'; did you mean 'timeGetTime'? [-Wimplicit-function-declaration]
580 | res = timer_settime(timerId, 0, &its, NULL);
| ^~~~~~~~~~~~~
| timeGetTime
test.c:160:19: warning: unused variable 'sev' [-Wunused-variable]
560 | struct sigevent sev = { 0 };
So, what I want to achieve, is a periodic timer callback of a function at a period of 10 ms (as tight as possible (*)), with C code that can compile with gcc under both MINGW64 and Linux.
Is it possible to achieve this - and if so, how? (maybe there is a library that facilitates this?)
(*) - in my experiments with MINGW64 builds on Windows 10, I've seen that nanosleep(&ts, &ts); in a while loop in main() with timestamp printouts, -- where ts = {.tv_sec = 0, .tv_nsec = 500 * 1000000} describes an interval of half a second, -- can measure anywhere between 505 and 520 ms; so I'm not sure how "tight" of a 10 ms period will be achievable - but I'd still love to know about options to implement a cross-platform periodic timer, even with a poorer timer resolution ...

Related

time_t was not declared in this scope; did you mean 'size_t'? compile error

it shows do you mean size_t where time_t was used and others
at the end shows error compiling c files
I Tried installing openplc code form github using cygwin but the below error message shows
Generating object files...
In file included from Config0.c:6:
./lib/iec_std_lib.h: In function ‘TIME __time_mul(TIME, LREAL)’:
./lib/iec_std_lib.h:376:3: error: ‘time_t’ was not declared in this scope; did you mean ‘size_t’?
376 | time_t s = (time_t)s_f;
| ^~~~~~
| size_t
./lib/iec_std_lib.h:378:21: error: ‘s’ was not declared in this scope; did you mean ‘ns’?
378 | TIME res = {(long)s + ns.quot,
| ^
| ns
./lib/iec_std_lib.h: In function ‘TIME __time_div(TIME, LREAL)’:
./lib/iec_std_lib.h:385:3: error: ‘time_t’ was not declared in this scope; did you mean ‘size_t’?
385 | time_t s = (time_t)s_f;
| ^~~~~~
| size_t
./lib/iec_std_lib.h:386:21: error: ‘s’ was not declared in this scope
386 | TIME res = {(long)s,
| ^
./lib/iec_std_lib.h: In function ‘STRING __tod_to_string(TOD)’:
./lib/iec_std_lib.h:623:5: error: ‘time_t’ was not declared in this scope; did you mean ‘size_t’?
623 | time_t seconds;
| ^~~~~~
| size_t
./lib/iec_std_lib.h:625:5: error: ‘seconds’ was not declared in this scope
625 | seconds = IN.tv_sec;
| ^~~~~~~
Error compiling C files
Compilation finished with errors!
You must include <time.h> for the definition of time_t to be visible to the compiler.
The error message is somewhat confusing: the compiler does not know about time_t but it has seen a definition of size_t that differs only by 2 letters so it hints of a potential typo or programmer mistake.

unknown type name while compiling C program

I am newbie to C program and I use Linux odroid 4.9.277-122 aarch64 GNU/Linux. I compiled the C program using make PLATFORM=gcc-linux-arm BUILD=release
In my main.C it use twMessages, twMessaging, twApi header files and I got the following error.
May I know why it gives unknown type name in the header file and how can I solve the issue?
Is it related to the platform= gcc-linux-arm that I used while compiling?
In file included from ../src/twMessages.h:13,
from ../src/twMessaging.h:7,
from ../src/twApi.h:21,
from ../src/main.c:99:
../src/twInfoTable.h:88:2: error: unknown type name 'twList'
88 | twList * aspects; /**< A ::twList of the aspects associated with the entry. **/
| ^~~~~~
../src/twMessages.h:68:2: error: unknown type name 'twList'
68 | twList * headers;
| ^~~~~~
../src/twApi.h:166:2: error: unknown type name 'twList'
166 | twList * bindEventCallbackList; /**< Pointer to a ::twList of bind event callbacks. **/
| ^~~~~~
In file included from ../src/main.c:99:
../src/twApi.h:30:22: error: unknown type name 'twList'; use 'struct' keyword to refer to the type
30 | #define propertyList twList /* A propertyList is a twList */

Why does a simple array cause gcc to fail without a error message?

following code when included in kernel.h
#define MEMORY_GB 1
#define MEMORY_SIZE 100000*1024*MEMORY_GB
char memory[MEMORY_SIZE];
causes gcc to stop working
make: *** [kernel.x86_64.elf] Error 1
In file included from kernel.c:111:
libs/graphics.h: At top level:
libs/graphics.h:12:6: warning: conflicting types for 'cleardevice'
12 | void cleardevice(){
| ^~~~~~~~~~~
kernel.c:90:9: note: previous implicit declaration of 'cleardevice' was here
90 | cleardevice();
| ^~~~~~~~~~~
In file included from kernel.c:111:
libs/graphics.h:28:6: warning: conflicting types for 'setbkcolor'
28 | void setbkcolor(uint32_t color){
| ^~~~~~~~~~
kernel.c:89:9: note: previous implicit declaration of 'setbkcolor' was here
89 | setbkcolor(YELLOW);
| ^~~~~~~~~~
In file included from kernel.c:114:
idt.h:25:6: warning: conflicting types for 'InitializeIDT'
25 | void InitializeIDT(){
| ^~~~~~~~~~~~~
kernel.c:69:5: note: previous implicit declaration of 'InitializeIDT' was here
69 | InitializeIDT();
| ^~~~~~~~~~~~~
In file included from kernel.c:114:
idt.h: In function 'InitializeIDT':
idt.h:38:2: warning: implicit declaration of function 'RemapPic' [-Wimplicit-function-declaration]
38 | RemapPic();
| ^~~~~~~~
idt.h: At top level:
idt.h:46:6: warning: conflicting types for 'RemapPic'
46 | void RemapPic(){
| ^~~~~~~~
idt.h:38:2: note: previous implicit declaration of 'RemapPic' was here
38 | RemapPic();
| ^~~~~~~~
In file included from kernel.c:113:
core/memory.h: In function 'malloc':
core/memory.h:27:1: warning: control reaches end of non-void function [-Wreturn-type]
27 | }
| ^
In file included from kernel.c:115:
drivers/ps2/keyboard.h: In function 'scanCodeToKey':
drivers/ps2/keyboard.h:9:1: warning: control reaches end of non-void function [-Wreturn-type]
9 | }
on terminal there is no errors outputted by gcc in first place which is odd it returns with 1 as exit code which make complains about that, but when array size changed to 1 it magically works aren't there is no limit for array size in C? Another odd thing is even though this fail happens in build time and there shouldn't be a issue with the kernel itself
Another odd finding when i remove the macros and directly write with a random length like 400
char memory[400];
again same issue huh but
char memory[1];
works perfectly fine
Despite my attempts at googling why something like happens there was no results.
Here is some information about my system:
Build Env: Linux Lubuntu
Compiler: Gnu Gcc cross compiler x86_64-elf-gcc (GCC) 10.2.0
Sidenote: Kernel was working perfectly just the issue is that weird array problem on the memory manager

nanosleep() wait for at least 15 ms?

In order to make a good timing in an emulator, I have to wait for around 50 microseconds.
When I use nanosleep, for example with a duration of 10 microsecs, I measure a delay of 15 millisec ! I use mingw on windows with the following example code :
#include <stddef.h>
#include <time.h>
#include <stdio.h>
int main()
{
struct timespec startx, endx;
struct timespec req={0};
req.tv_sec=0;
req.tv_nsec=10000; // 10_000 ns = 10 microseconds
for (int i=0; i<10; i++)
{
clock_gettime(CLOCK_MONOTONIC, &startx);
nanosleep(&req, NULL);
clock_gettime(CLOCK_MONOTONIC, &endx);
if (endx.tv_sec-startx.tv_sec)
printf("%li microsecs\n",((endx.tv_nsec-startx.tv_nsec)/1000)+1000000);
else
printf("%li microsecs\n",(endx.tv_nsec-startx.tv_nsec)/1000);
}
return 0 ;
}
And the result is :
12528 microsecs
19495 microsecs
14890 microsecs
14229 microsecs
14657 microsecs
14824 microsecs
14724 microsecs
21074 microsecs
13697 microsecs
13893 microsecs
I guess I'm wrong somewhere....
If someone has an idea. I could also avoid the problem with a "do nop while (end-start) < 50usec"...
Thanks.
When I run the posted code through a compiler (gcc) the compiler outputs the following:
gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o"
untitled1.c: In function ‘main’:
untitled1.c:16:57: error: ‘err’ undeclared (first use in this function)
16 | if (nanosleep(&req, NULL)) printf("err : %i\n", err);
| ^~~
untitled1.c:16:57: note: each undeclared identifier is reported only once for each function it appears in
untitled1.c:18:18: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘__syscall_slong_t’ {aka ‘long int’} [-Wformat=]
18 | printf("%d microsecs %d\n",(endx.tv_nsec-startx.tv_nsec)/1000, endx.tv_sec-startx.tv_sec);
| ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| int __syscall_slong_t {aka long int}
| %ld
untitled1.c:18:31: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘__time_t’ {aka ‘long int’} [-Wformat=]
18 | printf("%d microsecs %d\n",(endx.tv_nsec-startx.tv_nsec)/1000, endx.tv_sec-startx.tv_sec);
| ~^ ~~~~~~~~~~~~~~~~~~~~~~~~~
| | |
| int __time_t {aka long int}
| %ld
Compilation failed.
When compiling, always enable the warnings, then fix those warnings.
to start, suggest casting the result of the call to time() to be a long int
as to your question:
context switches take time AND the cpu(s) are probably busy with other tasks AND the task scheduler only looks at the list of tasks ready to run periodically , so your request will not be immediately serviced.
to obtain a more accurate timing, do not depend on the OS. Rather use one of the hardware timers to produce a interrupt event when you want the elapsed time to expire. Then use an interrupt handler to handle the interrupt event from the hardware timer.

Unknown type when compiling XZ Utils on MinGW/MSYS2

I've been trying to compile XZ Utils using MinGW-w64 and when trying to run make after ./configureing, I get the error that sigset_t is unknown.
The XZ Utils version is 5.2.3, and my MinGW-w64 is x86_64-7.2.0-posix-seh-rt_v5-rv1.
In file included from common/common.h:17:0,
from common/common.c:13:
../../src/common/mythread.h:138:33: error: unknown type name 'sigset_t'
mythread_sigmask(int how, const sigset_t *restrict set,
^~~~~~~~
../../src/common/mythread.h:139:3: error: unknown type name 'sigset_t'; did you mean '_sigset_t'?
sigset_t *restrict oset)
^~~~~~~~
_sigset_t
../../src/common/mythread.h: In function 'mythread_create':
../../src/common/mythread.h:158:2: error: unknown type name 'sigset_t'; did you mean '_sigset_t'?
sigset_t old;
^~~~~~~~
_sigset_t
../../src/common/mythread.h:159:2: error: unknown type name 'sigset_t'; did you mean '_sigset_t'?
sigset_t all;
^~~~~~~~
_sigset_t
../../src/common/mythread.h:160:2: warning: implicit declaration of function 'sigfillset' [-Wimplicit-function-declaration]
sigfillset(&all);
^~~~~~~~~~
../../src/common/mythread.h:162:2: warning: implicit declaration of function 'mythread_sigmask'; did you mean 'pthread_sigmask'? [-Wimplicit-function-declaration]
mythread_sigmask(SIG_SETMASK, &all, &old);
^~~~~~~~~~~~~~~~
pthread_sigmask
I checked signal.h for sigset_t using gcc -E - <<< "#include <signal.h>" | grep sigset_t and found nothing. Now I've been wondering if this is a MinGW limitation and, if yes, if there is a way around it.
https://github.com/Alexpux/mingw-w64/blob/master/mingw-w64-headers/crt/sys/types.h#L110
#ifdef _POSIX
typedef _sigset_t sigset_t;
#endif
It appears this only gets defined if _POSIX is defined. It also is in sys/types.h vs. signal.h...

Resources