Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions 05_timers/kernel_module/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
KERNELDIR ?= ../../../buildroot/buildroot-2021.02.7/output/build/linux-5.10.7/ #WARNING relative path

obj-m := mytimeobj.o

all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
89 changes: 89 additions & 0 deletions 05_timers/kernel_module/mytimeobj.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// SPDX-License-Identifier: GPL-2.0-only

#include <linux/module.h>
#include <linux/kobject.h>
#include <linux/err.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/ktime.h>

MODULE_AUTHOR("Nazarii Kurylko <kurylko.n@gmail.com>");
MODULE_DESCRIPTION("time in kernel module");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1");

static ssize_t time_prev_call_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
static struct timespec64 ts_prev;
ssize_t count;

count = scnprintf(buf, PAGE_SIZE, "%llds.%ldns\n", ts_prev.tv_sec,
ts_prev.tv_nsec);

ktime_get_real_ts64(&ts_prev);
return count;
}

static ssize_t time_since_prev_call_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct timespec64 ts;
ktime_t now = 0;
static int inited;
static ktime_t prev;

now = ktime_get();
if (!inited) {
prev = now;
inited = 1;
}

now = ktime_get();
ts = ktime_to_timespec64(ktime_sub(now, prev));
prev = now;

return scnprintf((char *)buf, PAGE_SIZE, "%llds.%ldns\n", ts.tv_sec,
ts.tv_nsec);
}

static struct kobj_attribute attribute1 =
__ATTR(time_prev_call, 0444, time_prev_call_show, NULL);

static struct kobj_attribute attribute2 =
__ATTR(time_since_prev_call, 0444, time_since_prev_call_show, NULL);

static struct kobject *myobject_kobj;

static struct attribute *attrs[] = {
&attribute1.attr, &attribute2.attr, NULL,
/* need to NULL terminate the list of attributes */
};

static struct attribute_group attr_group = {
.attrs = attrs,
};

static int myobject_init(void)
{
int res = 0;

myobject_kobj = kobject_create_and_add("MyTimeObject", kernel_kobj);
if (!myobject_kobj)
return -ENOMEM;
res = sysfs_create_group(myobject_kobj, &attr_group);
if (res)
kobject_put(myobject_kobj);

return res;
}

static void myobject_exit(void)
{
kobject_put(myobject_kobj);
}

module_init(myobject_init);
module_exit(myobject_exit);
11 changes: 11 additions & 0 deletions 05_timers/userspace_time/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
default: mytime

rpscissors.o: mytime.c
gcc -c mytime.c -o mytime.o

rpscissors: mytime.o
gcc mytime.o -o mytime

clean:
-rm -f mytime.o
-rm -f mytime
80 changes: 80 additions & 0 deletions 05_timers/userspace_time/mytime.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// SPDX-License-Identifier: 0BSD
/**
* Description: My Time
* Author: Nazarii Kurylko
* Created: 09.12.2021
**/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

// see https://man7.org/linux/man-pages/man3/clock_gettime.3.html for details

clockid_t clk_id_arr[] = { CLOCK_REALTIME, CLOCK_REALTIME_ALARM,
CLOCK_REALTIME_COARSE, CLOCK_TAI,
CLOCK_MONOTONIC, CLOCK_MONOTONIC_RAW,
CLOCK_MONOTONIC_COARSE, CLOCK_PROCESS_CPUTIME_ID,
CLOCK_THREAD_CPUTIME_ID, CLOCK_BOOTTIME,
CLOCK_BOOTTIME_ALARM };

char *clk_id_arr_str[] = {
"CLOCK_REALTIME", "CLOCK_REALTIME_ALARM",
"CLOCK_REALTIME_COARSE", "CLOCK_TAI",
"CLOCK_MONOTONIC", "CLOCK_MONOTONIC_RAW",
"CLOCK_MONOTONIC_COARSE", "CLOCK_PROCESS_CPUTIME_ID",
"CLOCK_THREAD_CPUTIME_ID", "CLOCK_BOOTTIME",
"CLOCK_BOOTTIME_ALARM"
};

int timespec2str(char *buf, uint len, struct timespec *ts)
{
int ret;
struct tm t;

tzset();
if (localtime_r(&(ts->tv_sec), &t) == NULL)
return 1;

ret = strftime(buf, len, "%F %T", &t);
if (ret == 0)
return 2;
len -= ret - 1;

ret = snprintf(&buf[strlen(buf)], len, ".%09ld", ts->tv_nsec);
if (ret >= len)
return 3;

return 0;
}

/*main algorithm*/
int main(int argc, char **argv)
{
static int i;
static struct timespec mytime, mytimeres;
char tmp[100];

for (i = 0; i < ARRAY_SIZE(clk_id_arr); ++i) {
//print clock output
if (!clock_gettime(clk_id_arr[i], &mytime))
printf("%s: time: %ld sec, %ld nsec\n",
clk_id_arr_str[i], mytime.tv_sec,
mytime.tv_nsec);
//print time in formated string
timespec2str(tmp, sizeof(tmp), &mytime);
printf("%s: %s\n", clk_id_arr_str[i], tmp);

//print clock resolution
if (!clock_getres(clk_id_arr[i], &mytimeres))
printf("%s: resolution: %ld sec, %ld nsec\n",
clk_id_arr_str[i], mytimeres.tv_sec,
mytimeres.tv_nsec);
printf("==================================\n");
}

return 0;
}