バイナリー・ファイル./linux-2.6.18.1/Documentation/.kprobes.txt.swpとlinux-2.6.18.1-cabi-20070524-hrt-nrt/Documentation/.kprobes.txt.swpは違います diff -urN ./linux-2.6.18.1/Makefile linux-2.6.18.1-cabi-20070524-hrt-nrt/Makefile --- ./linux-2.6.18.1/Makefile 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/Makefile 2007-05-10 17:19:13.000000000 +0900 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 18 -EXTRAVERSION = .1 +EXTRAVERSION = .1-cabi-eval NAME=Avast! A bilge rat! # *DOCUMENTATION* @@ -522,7 +522,7 @@ # # INSTALL_PATH specifies where to place the updated kernel and system map # images. Default is /boot, but you can set it to other values -export INSTALL_PATH ?= /boot +export INSTALL_PATH = /boot # # INSTALL_MOD_PATH specifies a prefix to MODLIB for module directory @@ -598,6 +598,10 @@ # # System.map is generated to document addresses of all kernel symbols +ifeq ($(strip $(CONFIG_CABI)),y) +libgcc=$(shell $(CC) -print-libgcc-file-name) +endif + vmlinux-init := $(head-y) $(init-y) vmlinux-main := $(core-y) $(libs-y) $(drivers-y) $(net-y) vmlinux-all := $(vmlinux-init) $(vmlinux-main) diff -urN ./linux-2.6.18.1/arch/i386/Kconfig linux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/Kconfig --- ./linux-2.6.18.1/arch/i386/Kconfig 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/Kconfig 2007-01-09 23:14:17.000000000 +0900 @@ -803,8 +803,11 @@ If unsure, say Y. +source "drivers/cabi/Kconfig" + endmenu + config ARCH_ENABLE_MEMORY_HOTPLUG def_bool y depends on HIGHMEM @@ -966,6 +969,7 @@ source "arch/i386/kernel/cpu/cpufreq/Kconfig" + endmenu menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" バイナリー・ファイル./linux-2.6.18.1/arch/i386/boot/bzImage.1000hzとlinux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/boot/bzImage.1000hzは違います diff -urN ./linux-2.6.18.1/arch/i386/kernel/entry.S linux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/kernel/entry.S --- ./linux-2.6.18.1/arch/i386/kernel/entry.S 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/kernel/entry.S 2007-05-23 20:59:43.000000000 +0900 @@ -229,6 +229,7 @@ ret_from_exception: preempt_stop ret_from_intr: + GET_THREAD_INFO(%ebp) check_userspace: movl EFLAGS(%esp), %eax # mix EFLAGS and CS @@ -239,6 +240,15 @@ cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret +#ifdef CONFIG_CABI + movl cabi_ret_with_reschedule_hook,%eax + testl %eax,%eax /* if (hook == 0) */ + je 1f /* yes, then skip it */ + call *%eax /* no, then call hook */ + testl %eax,%eax /* if (ret != 0) */ + jne resume_userspace /* yes, then jump back */ +1: +#endif movl TI_flags(%ebp), %ecx andl $_TIF_WORK_MASK, %ecx # is there any work to be done on # int/exception return? @@ -359,6 +369,17 @@ cli # make sure we don't miss an interrupt # setting need_resched or sigpending # between sampling and the iret + +#ifdef CONFIG_CABI + movl cabi_ret_with_reschedule_hook,%eax + testl %eax,%eax /* if (hook == 0) */ + je 1f /* yes, then skip it */ + call *%eax /* no, then call hook */ + testl %eax,%eax /* if (ret != 0) */ + jne syscall_exit /* yes, then jump back */ +1: +#endif + TRACE_IRQS_OFF movl TI_flags(%ebp), %ecx testw $_TIF_ALLWORK_MASK, %cx # current->work @@ -384,6 +405,17 @@ 1: iret .section .fixup,"ax" iret_exc: + +#ifdef CONFIG_CABI + movl cabi_ret_with_reschedule_hook,%eax + testl %eax,%eax /* if (hook == 0) */ + je 1f /* yes, then skip it */ + call *%eax /* no, then call hook */ + testl %eax,%eax /* if (ret != 0) */ + jne iret_exc /* yes, then jump back */ +1: +#endif + TRACE_IRQS_ON sti pushl $0 # no error code diff -urN ./linux-2.6.18.1/arch/i386/kernel/syscall_table.S linux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/kernel/syscall_table.S --- ./linux-2.6.18.1/arch/i386/kernel/syscall_table.S 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/arch/i386/kernel/syscall_table.S 2007-05-08 14:25:09.000000000 +0900 @@ -317,3 +317,14 @@ .long sys_tee /* 315 */ .long sys_vmsplice .long sys_move_pages +#ifdef CONFIG_CABI + .long sys_cabi_account_create /* 318-324 */ + .long sys_cabi_account_destroy + .long sys_cabi_account_bind_pid + .long sys_cabi_account_bind_pgid + .long sys_cabi_account_unbind + .long sys_cabi_account_get + .long sys_cabi_account_set + .long sys_cabi_account_eval +#endif /* CONFIG_CABI */ + diff -urN ./linux-2.6.18.1/drivers/Makefile linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/Makefile --- ./linux-2.6.18.1/drivers/Makefile 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/Makefile 2007-01-09 23:14:57.000000000 +0900 @@ -76,3 +76,4 @@ obj-$(CONFIG_SUPERH) += sh/ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ +obj-$(CONFIG_CABI) += cabi/ diff -urN ./linux-2.6.18.1/drivers/cabi/Kconfig linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/Kconfig --- ./linux-2.6.18.1/drivers/cabi/Kconfig 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/Kconfig 2007-01-09 23:15:23.000000000 +0900 @@ -0,0 +1,10 @@ +# +# CABI related configuration option +# + +config CABI + bool 'CPU Accounting and Binding Interface support' + default n + ---help--- + CPU Accounting and Binding Interface support. + diff -urN ./linux-2.6.18.1/drivers/cabi/Makefile linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/Makefile --- ./linux-2.6.18.1/drivers/cabi/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/Makefile 2007-04-23 21:42:08.000000000 +0900 @@ -0,0 +1,15 @@ +# +# Makefile for the linux kernel. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definitions are now in the main makefile... + + +obj-$(CONFIG_CABI) = cabi_init.o cabi_account.o cabi_timer.o cabi_sched.o cabi_isr.o cabi_signal.o udivdi3.o cabi_overload.o cabi_syscalls.o cabi_debug.o cabi_cyclic.o cabi_defsrv.o +#cabi_dsv_replenish.o cabi_cyc_isr.o cabi_dsv_isr.o cabi_ovl_isr.o cabi_ovl_replenish.o +obj-$(CONFIG_PROC_FS) += cabi_procfs.o + + diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_account.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_account.c --- ./linux-2.6.18.1/drivers/cabi/cabi_account.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_account.c 2007-06-17 00:30:11.000000000 +0900 @@ -0,0 +1,1179 @@ +/* + * linux/drivers/cabi/cabi_account.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * 2007 Modified by Midori Sugaya to change interfaces. + * 2006-9-12. Modified by Midori Sugaya to fix bugs in tick calculation + * and make adjustment for 2.6. + * 2006-2. Porting to kernel-2.6 Takeharu KATO (ARM, SH) + * 2005-2. New release based on LinuxRK. by Midori SUGAYA, Hirotaka + * ISHIKAWA. + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * Static variables for accounting + */ + +/* + * This values keeps the initial address of the accounting + * object and overload accounting object which currently + * running. + */ + +cabi_account_t cabi_current_account; +cabi_account_t cabi_current_overload_account; + +/* + * Current capacity which current accounting object holds. + */ +cpu_capacity_t cabi_account_current_capacity; + +/* + * Other global variables. + */ +struct list_head cabi_account_head; +int overload_cabi; +int last_cabi_id = 0; + +extern long sys_setpgid(pid_t pid, pid_t pgid); +extern rwlock_t tasklist_lock; + +/* + * Name: cabi_account_init + * + * Initialize the variables which are used in the accounting. + * This function is called from the cabi_init which is executed + * during kernel start boot. + */ +void +cabi_account_init(void) +{ + ENTER; + INIT_LIST_HEAD(&cabi_account_head); + cabi_account_current_capacity = 0; + cabi_current_account = NULL_ACCOUNT; + cabi_current_overload_account = NULL; + EXIT; +} + +/* + * Name: search_cabi (cabi_id) + * + * Search the accounting object (cabi) which is specified by the + * argument with cabi_id. Return the initial address of the + * accounting object. + */ + +cabi_account_t +search_cabi(unsigned long cabi_id) +{ + + struct list_head *cabi_list; + cabi_account_t cabi = NULL_ACCOUNT; + + cabi_list = &cabi_account_head; + + while (!list_empty(cabi_list)) { + cabi = list_entry(cabi_list, struct cabi_account, cpu_link); + + if (cabi->cabi_id == cabi_id) + break; + + cabi_list = cabi_list->next; + if (cabi_list == &cabi_account_head) { + cabi = NULL_ACCOUNT; + break; + } + } + return cabi; +} + +/* + * Name: get_cabi_id (void) + * + * Return unique accounting object id for the caller. In this + * function, duplicate ids and reserved ids are carafully + * asided from the id pools. CABI_ID_MAX keeps the maximum + * limit of the id which is defined in cabi.h header. + */ + +int +get_cabi_id(void) +{ + struct list_head *cabi_list; + cabi_account_t cabi = NULL_ACCOUNT; + int begin_cabi_id, cabi_id_error; + cabi_id_error = -1; + + begin_cabi_id = -1; + last_cabi_id++; + + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + if (cabi_list == &cabi_account_head) { /* First AO create. */ + last_cabi_id = FIRST_CABI_ID; + return last_cabi_id; + } + while (!list_empty(cabi_list)) { /* Get cabi_id */ + cabi = list_entry(cabi_list, struct cabi_account, cpu_link); + /* cabi_id is full */ + if (last_cabi_id == begin_cabi_id) + return cabi_id_error; + /* selected cabi_id is for overload */ + if (OVERLOAD_CABI_ID == last_cabi_id) { + if (begin_cabi_id == -1) + begin_cabi_id = last_cabi_id; + ++last_cabi_id; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* selected cabi_id is already used */ + if (cabi->cabi_id == last_cabi_id) { + if (begin_cabi_id == -1) + begin_cabi_id = last_cabi_id; + ++last_cabi_id; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* selected cabi_id is MAX value */ + + if (last_cabi_id >= CABI_ID_MAX) { + if (begin_cabi_id == -1) + begin_cabi_id = last_cabi_id; + last_cabi_id = FIRST_CABI_ID; + cabi_list = &cabi_account_head; + cabi_list = cabi_list->next; + continue; + } + /* next cabi list */ + cabi_list = cabi_list->next; + + /* all lists were searched. */ + if (cabi_list == &cabi_account_head) + break; + } + return last_cabi_id; +} + +/* + * Capacity calculation of accounting object (cabi) + */ + +cpu_capacity_t +capacity_of(cpu_capacity_quad_t qc, cpu_capacity_quad_t qt) +{ + + unsigned long long qc_tmp, qt_tmp; /* unsigned long long */ + unsigned long result, rem; /* unsigned long */ + + ENTER; + + /* to store fine grained value, we use 10000 instead of + 100 for deviding. */ + qc_tmp = (unsigned long long) qc * 10000; + qt_tmp = (unsigned long long) qt; + + if (qt_tmp > 1000000000) { + qc_tmp = qc_tmp >> 8; + qt_tmp = qt_tmp >> 8; + } + + result = (unsigned long) + div_long_long_rem (qc_tmp, qt_tmp, &rem); + + cabi_debug_capacity(result); + + EXIT; + return result; +} + +void +set_terminate_operation (struct cabi_account *cabi) +{ + + switch (cabi->pm.operation){ + case OP_NONE: + break; + case OP_BLOCK: + cabi->opt_state = CABI_UNBLOCK; + break; + case OP_SIGNAL: + cabi->opt_state = CABI_SIGNAL; + break; + default: + break; + } +} + +int +capacity_admission_control (cabi_param_data_t *p, + cpu_capacity_t capacity) +{ + + cabi_account_current_capacity = + capacity + cabi_account_current_capacity; + + switch (p->policy) { + case PO_DEFSRV: + break; + case PO_EDF: + //if (cabi_account_current_capacity > 99) + // return 0; + break; + case PO_RM: + //if (cabi_account_current_capacity > 69) + // return 0; + break; + default: + break; + } + + return 1; +} + + +/* + * Name: cabi_account_create + * + * Create a accounting object. The function called from + * sys_cabi_account_create which is a interface of the system call. + */ + +cabi_account_t +cabi_account_create(struct timespec *c, struct timespec *t, + cabi_param_data_t * p) +{ + + cabi_account_t cabi; + cpu_capacity_t capacity; + cpu_capacity_quad_t qc, qt, overload_qc; + long get_id = 0; + + + ENTER; + cabi_debug_timespecs(c,t); + + /* + * if this is overload cabi, calculate parameters. + */ + if (p->bind_proc_type == BIND_IDLE_PROC){ + capacity_overload(c,t,&overload_qc); + qc = overload_qc; + } else { + qc = ((unsigned long long)c->tv_sec * NANOSEC) + + (unsigned long long)c->tv_nsec; + } + qt = ((unsigned long long)t->tv_sec * NANOSEC) + + (unsigned long long)t->tv_nsec; + + + /* capacity is the rate of qc/qt * 100 */ + cabi_debug_ct (qc, qt); + capacity = capacity_of (qc, qt); + cabi_debug_capacity (capacity); + + /* + * Add the new capacity to the global capacity + * This is the point that admission control should be taken + * by its policy + */ + capacity_admission_control(p, capacity); + + cabi_debug_capacity(cabi_account_current_capacity); + + /* create an accounting object */ + if((cabi = malloc(sizeof (struct cabi_account))) == NULL) + return NULL; + bzero(cabi, sizeof (struct cabi_account)); + + /* memory copy */ + memcpy(&cabi->pm, p, sizeof(struct cpu_param)); + + /* + * Set up the unique id for cabi. Firtst, check whether the + * the cabi is for the overload or not. If overload, a special + * id should be set. If not, set a sequencial number for it. + */ + if (cabi->pm.bind_proc_type | IDLE_PROCESS) { + /* if it is for overload, setup the overload id */ + setup_overload_id (cabi); + + } else { + if((get_id = get_cabi_id()) < 0) { + free(cabi); + return NULL; + } else { + cabi->cabi_id = (unsigned int)get_id; + } + } + CABI_DBG; + cabi_debug("[create] cabi_id %lu\n", cabi->cabi_id); + + /* + * Initialize the list head for proc list. + */ + INIT_LIST_HEAD(&cabi->cpu_proc_list); + memcpy (&cabi->cpu_time, c, sizeof(struct timespec)); + memcpy (&cabi->cpu_period, t, sizeof(struct timespec)); + cabi->cpu_capacity = capacity; + + /* + * if this is the first call as the requirement of reservation, + * we should set up cabi hooks. + */ + if (list_empty(&cabi_account_head)) { + /* enable scheduling hook */ + cabi_enable(); + } + list_add(&cabi->cpu_link, &cabi_account_head); + + /* calculate cpu ticks per capacity */ + /* to pass the nanosec value to the usec2tick interface, + * we devide the nanosec value by 1000 into the usec. + */ + nanosec2tick(&qc, &cabi->cpu_time_ticks); + nanosec2tick(&qt, &cabi->cpu_period_ticks); + + /* cabi debug ticks */ + + /* + * Let the account replenished from the next jiffy. + * See also cabi_timer.c:cabi_replenish_timer_create(). + * cpu_period_used_ticks = 0; + * cpu_period_available_ticks = 0; + */ + /* init waitqueue */ + init_waitqueue_head(&cabi->depleted_wait); + + /* create entry as /proc/cabi/ */ + INIT_LIST_HEAD(&cabi->cpu_proc_list); + cabi->cpu_state = CABI_IS_DEPLETED; + cabi->signal_block = SIGNAL_OFF; + +#ifdef CONFIG_PROC_FS + cabi_proc_account_create(cabi); +#endif + set_terminate_operation(cabi); + set_account_policy(cabi); + + return cabi; /* success */ +} + +/* + * Name: cabi_account_destroy + * + * Delete a accounting object from kernel memory. The function called from + * sys_cabi_account_destroy which is a interface of the system call. + */ + +int +cabi_account_destroy(unsigned long cabi_id) +{ + cabi_account_t cabi = NULL_ACCOUNT; + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) + return CABI_ENOEXIST; + + /* if account has attached pgrocesses */ + if (!list_empty(&cabi->cpu_proc_list)) + /* process is still attached. */ + return CABI_EATTACHED; + + /* destroy timer */ + cabi_replenish_timer_cancel(cabi); + + /* return capacity */ + if (cabi->cpu_capacity >= cabi_account_current_capacity) { + cabi_account_current_capacity = 0; + } else { + cabi_account_current_capacity -= cabi_account_current_capacity; + } + + /* delete cpu_link */ + list_del(&cabi->cpu_link); + INIT_LIST_HEAD(&cabi->cpu_link); /* for sure */ + cabi->pm.operation = OP_NONE; + CABI_DBG; + +#ifdef CONFIG_PROC_FS + /* + * remove entry under /proc/cabi/ + * must be before cabi_resource_set_detach_account() + * since resource_set is reffered in cabi_proc_account_destroy() + */ + cabi_proc_account_destroy(cabi); +#endif + + /* finally free a generic account object. */ + free(cabi); + + if (cabi_id == OVERLOAD_CABI_ID) + cabi_current_overload_account = NULL; + + /* if this is the last cabi, disable_isr */ + if (!cabi_account_current_capacity) + cabi_disable(); + + return CABI_SUCCESS; /* success */ +} + + +/* + * Name: cabi_account_set + * + * Set a parameter for accounting object. The function called from + * sys_cabi_account_set which is a interface of the system call. + */ + +int +cabi_account_set(unsigned long cabi_id, struct timespec *c, + struct timespec *t, cabi_param_data_t * p) +{ + cpu_capacity_t capacity; + cpu_capacity_quad_t qc, qt, overload_qc; + cabi_account_t cabi = NULL_ACCOUNT; + + ENTER; + + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) { + /* cabi dose not exist. */ + return CABI_ENOEXIST; + } + + /* check timespec */ + cabi_debug_timespecs(&cabi->cpu_time, &cabi->cpu_period); + cabi_debug_timespecs(c,t); + + /* cabi is depleted */ + cabi->cpu_state = CABI_IS_DEPLETED; + + /* set terminate action */ + memcpy(&cabi->pm, p, sizeof(cabi_param_data_t)); + + if(cabi->pm.operation == OP_BLOCK) { + cabi->opt_state = CABI_UNBLOCK; + } else { + cabi->opt_state = CABI_SIGNAL; + if (!CABI_SIGNUM(cabi)) { + cabi->pm.operation = OP_NONE; + } + } + + /* if this is overload cabi, re-calculate parameters. */ + if (cabi->pm.bind_proc_type == BIND_IDLE_PROC){ + + /* debug timespec */ + cabi_debug_timespecs (c,t); + + /* new parameter has been set in the overload_qc */ + capacity_overload(c,t,&overload_qc); + qc = overload_qc; + } else { + qc = (c->tv_sec * NANOSEC) + c->tv_nsec; + } + qt = (t->tv_sec * NANOSEC) + t->tv_nsec; + + /* calculate a new capacity */ + capacity = capacity_of(qc, qt); + + /* set current capacity */ + cabi_account_current_capacity = + capacity + cabi_account_current_capacity - cabi->cpu_capacity; + + /* check the result */ + cabi_debug_capacity (capacity); + cabi_debug_capacity (cabi_account_current_capacity); + + /* load the new parameters */ + memcpy(&cabi->cpu_time, c, sizeof(struct timespec)); + memcpy(&cabi->cpu_period, t, sizeof(struct timespec)); + cabi->cpu_capacity = capacity; + + /* initialize available ticks */ + cabi->cpu_period_available_ticks = 0; + + /* calculate cabi ticks per capacity */ + nanosec2tick(&qc, &cabi->cpu_time_ticks); + nanosec2tick(&qt, &cabi->cpu_period_ticks); + + /* cancel replenish timer */ + cabi_replenish_timer_cancel(cabi); + + /* reset a timer for it */ + cabi_replenish_timer_init(cabi, &cabi->cpu_period_ticks); + + return CABI_SUCCESS; /* success */ + +} + +/* + * Name: cabi_account_attach + * + * Attach a process to specified accounting object. + */ + +int +cabi_account_attach(unsigned long cabi_id, struct task_struct *tsk) +{ + struct rs_proc_list *rs_proc; + cabi_account_t cabi = NULL_ACCOUNT; + unsigned long flags; + + ENTER; + + /* find the cabi address */ + if (!(cabi = search_cabi(cabi_id))) { + CABI_DBG; + /* did not exist. */ + return CABI_ENOEXIST; + } + CABI_DBG; + /* + * !!! Need to make sure cabi is really a account. + */ + LVAL_TASK_ACCOUNT(tsk) = cabi; + + /* show info */ + cabi_debug_info(cabi); + CABI_DBG; + + if((rs_proc = malloc(sizeof (struct rs_proc_list))) == NULL) + return CABI_ENOMEM; + CABI_DBG; + bzero(rs_proc, sizeof (struct rs_proc_list)); + + /* If there is no process bind to this cabi, + * we should set the replenish timer for it. + */ + CABI_DBG; + + if (list_empty(&cabi->cpu_proc_list)) { + cabi_replenish_timer_init(cabi,&cabi->cpu_period_ticks); + } + CABI_DBG; + + /* set proc file system for the new belonged process */ + rs_proc->rs_proc_task = tsk; + rs_proc->rs_proc_pid = tsk->pid; + + CABI_DBG; + + local_save_flags(flags); + { + local_irq_disable(); + list_add(&rs_proc->rs_proc_list, &cabi->cpu_proc_list); + } + local_irq_restore(flags); + + CABI_DBG; + + /* attach! */ + /* NOT YET fixed. + * if we set the rdtsc time from here, there are lag time + * between the current cpu_period_start_time and the time + * which initial_rep_timer will be set one jiffy after. + */ + CABI_DBG; + if (cabi->cpu_period_start_ticks == 0 && + rs_proc->rs_proc_task == current) { + + /* + * XXX consider offset time for RT-processes! + */ + cabi_rdticks(&cabi->cpu_period_start_ticks); + } + CABI_DBG; + + /* if this is the current process, + * make it the current account and start accouting now */ + if (current == tsk) { + + /* XXX atomic ? */ + if (cabi_current_account != cabi) { + + /* XXX cabi が RUNNING の間は NULL であることを + 保証できているか?できていれば assertion で + チェックできる */ + cabi_current_account = cabi; + + /* check account info */ + cabi_debug_info (cabi_current_account); + } + cabi_start_account(cabi); + + if (cabi->cpu_state & CABI_IS_DEPLETED) { + + /* start accounting */ + cabi_account_enforce(cabi); + } + CABI_DBG; + } + if (cabi->cabi_id == OVERLOAD_CABI_ID) + overload_cabi++; + + CABI_DBG; + + return CABI_SUCCESS; +} + +/* + * Name: cabi_account_detach + * + * Detach a process from a specified accounting object. + */ + +int +cabi_account_detach(struct task_struct *tsk) +{ + cabi_account_t cabi = TASK_ACCOUNT(tsk); + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + + /* show cabi info */ + cabi_debug_info (cabi); + + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + if (rs_proc->rs_proc_pid == tsk->pid) { + break; + } + /* next element */ + proc_list = proc_list->next; + } + + if (rs_proc && rs_proc->rs_proc_pid == tsk->pid) { + + /* show rs_proc info */ + cabi_debug_detach (rs_proc); + + /* remove rs_proc from the list */ + list_del(&rs_proc->rs_proc_list); + + /* free rs_proc */ + INIT_LIST_HEAD(&rs_proc->rs_proc_list); + free(rs_proc); + } + /* detach resource set from task */ + LVAL_TASK_ACCOUNT(tsk) = NULL_ACCOUNT; + + if (tsk->state != TASK_RUNNING) { + wake_up(&cabi->depleted_wait); + } + + return CABI_SUCCESS; +} + +void +set_account_policy (cabi_account_t cabi) +{ + + ENTER; + switch (cabi->pm.policy) { + case PO_NONE: + break; + case PO_CYCLIC: + CABI_DBG; + cabi->ops = &cyclic_ops; + break; + case PO_OVLD: + cabi->ops = &ovl_ops; + break; + case PO_RM: + break; + case PO_DEFSRV: + CABI_DBG; + cabi->ops = &dsv_ops; + break; + case PO_VPE: + break; + case PO_EDF: + break; + default: + CABI_DBG; + cabi->ops = &cyclic_ops; + break; + } + EXIT; +} + +/* + * Name: cabi_account_replenish + * + * This function is called when the periodic timer is expired. + * At this point, the accounting system update the status and + * values of the accounting object and initialize them for + * preparing the next period. + * + * T T + * |<---------->|<---------->| + * --|------------|------------|--->t + * t1 t2 t3.. + * + */ + +void +cabi_account_replenish(cabi_account_t cabi) +{ + cabi->ops->replenish (cabi); +} + + +/* + * Name: cabi_account_enforce + * + * This function will change the status of the accounting object + * to CABI_IS_DEPLETED which cpu_state has not been depleted yet. + */ + + +void +cabi_account_enforce(cabi_account_t cabi) +{ + + ENTER; + + + if (cabi->cabi_id != OVERLOAD_CABI_ID && + !(cabi->cpu_state & CABI_IS_DEPLETED)) { + + /* check state */ + cabi_debug_state(cabi); + + /* + * Here, the capacity of accounting system has + * been used up already. So, we have to change + * the status to IS_DEPLETED. + */ + + cabi->cpu_state |= CABI_IS_DEPLETED; + cabi_debug_state (cabi); + + /* set current account */ + cabi_current_account = cabi; + } + EXIT; +} + + +/* + * Name: cabi_account_check_enforce + * + * Check the cpu_state of the accounting object. If the + * available ticks of TSC is less than the used ticks, + * the status should be changed. Call cabi_account_enforce. + */ +inline void +cabi_account_check_enforce(cabi_account_t cabi) +{ + ENTER; + + if ((cabi->cabi_id != OVERLOAD_CABI_ID) && + cabi->cpu_period_used_ticks >= cabi->cpu_period_available_ticks) { + + /* debug tikcs */ + cabi_debug_ticks(cabi); + + /* enforcing a account */ + cabi_account_enforce(cabi); + } + EXIT; +} + +/* + * Start & Stop the account of CPU utilization. + */ +/* + * Name: cabi_start_account + * + * It saves the start time of the process computation time (C) + * with TSC (Time Stamp Counter). + * + * T + * |<-------------------------->|<-.. + * | C C | + * | <----------> <---> | + * | start end s e | + * --|----------------------------|--> t + * s: cabi_start_account + * e: cabi_stop_account + */ + +void +cabi_start_account(cabi_account_t cabi) +{ + + unsigned long long next; + + ENTER; + + /* debug */ + cabi_debug_ticks (cabi); + + /* + * This code is used for the illegal status for the + * accuonting. At this point, if both of the available_ticks + * and the used_ticks equal to zero and used_ticks exceeded + * by the available_ticks, their accounting object cpu_status + * should be CABI_IS_DEPLETED. No need to check the + * status. + */ + + if (cabi->cpu_period_available_ticks < cabi->cpu_period_used_ticks) { + cabi->cpu_state |= CABI_IS_DEPLETED; + goto start_account_out; + } + + /* + * We can't calculate the substraction if the number of the ticks + * larger than the 32bit. + */ + + if (CHECK_DEGIT(cabi->cpu_period_available_ticks) || + CHECK_DEGIT(cabi->cpu_period_used_ticks)) { + + next = cabi_subtract_ll(cabi->cpu_period_available_ticks, + cabi->cpu_period_used_ticks, + (cabi_account_t) cabi); + /* debug */ + cabi_debug_tick(next); + + } else { + next = cabi->cpu_period_available_ticks - + cabi->cpu_period_used_ticks; + /* debug */ + cabi_debug_tick(next); + + } + + /* + * To save the time of the start_account, set the rdticks at this + * point. After finishing the running, we will get the time of rdticks + * in cabi_stop_account function. + */ + cabi_rdticks(&cabi->cpu_period_start_ticks); + + switch (cabi->cpu_state) { + + case CABI_IS_NULL: + cabi_debug("[start:NULL] %x\n", (int)cabi->cpu_state); + cabi->cpu_state |= CABI_IS_RUNNING; + cabi_enforce_timer_start(cabi, &next); + cabi_debug("[start:NULL] %x\n", (int)cabi->cpu_state); + break; + case CABI_IS_DEPLETED: + cabi_debug("[start:DEPLETED] %x\n", (int)cabi->cpu_state); + cabi->cpu_state |= CABI_IS_RUNNING; + cabi_debug("[start:DEPLETED] %x\n", (int)cabi->cpu_state); + break; + case CABI_IS_RUNNING: /* must not be so */ + cabi_debug("[start:RUNNING] %x\n", (int)cabi->cpu_state); + cabi_debug_state (cabi); + cabi_enforce_timer_start(cabi, &next); + cabi_debug("[start:RUNNING] %x\n", (int)cabi->cpu_state); + break; + case CABI_IS_RUNNING | CABI_IS_DEPLETED: + cabi_debug("[start:RUN|DEP] %x\n", (int)cabi->cpu_state); + cabi_debug_state (cabi); + break; + default: + /* unkown */ + cabi_debug("[start:default] %x\n", (int)cabi->cpu_state); + cabi_debug_state (cabi); + cabi_debug_tick (next); + cabi->cpu_state = CABI_IS_RUNNING; + + if (next > 0) { + cabi_debug_tick(next); + cabi_enforce_timer_start(cabi, &next); + } else { + cabi->cpu_state |= CABI_IS_DEPLETED; + } + cabi_debug("[start:default] %x\n", (int)cabi->cpu_state); +start_account_out: + break; + + } + + EXIT; + +} + + +void +cabi_stop_account(cabi_account_t cabi, cpu_tick_t now) +{ + + long long left; + + cabi_enforce_timer_cancel(); + cabi_account_summation_of_used_ticks(cabi, now); + + /* check state */ + cabi_debug_state (cabi); + + switch (cabi->cpu_state) { + + case CABI_IS_RUNNING: + cabi_debug ("[stop:b:RUN] %x\n", (int)cabi->cpu_state); + cabi->cpu_state &= ~CABI_IS_RUNNING; + cabi_account_check_enforce(cabi); + cabi_debug ("[stop:a:RUN] %x\n", (int)cabi->cpu_state); + break; + case CABI_IS_RUNNING | CABI_IS_DEPLETED: + cabi_debug ("[stop:b:RUN|DEP] %x\n", (int)cabi->cpu_state); + cabi->cpu_state &= ~CABI_IS_RUNNING; + cabi_debug ("[stop:a:RUN|DEP] %x\n", (int)cabi->cpu_state); + break; + case CABI_IS_NULL: /* must not be so */ + cabi_debug ("[stop:b:NULL] %x\n", (int)cabi->cpu_state); + cabi_debug_state(cabi); + cabi_account_check_enforce(cabi); + cabi_debug ("[stop:a:NULL] %x\n", (int)cabi->cpu_state); + break; + case CABI_IS_DEPLETED: /* must not be so */ + cabi_debug ("[stop:b:DEP] %x\n", (int)cabi->cpu_state); + cabi_debug_state(cabi); + cabi_debug ("[stop:a:DEP] %x\n", (int)cabi->cpu_state); + break; + default: /* unkown */ + left = + cabi->cpu_period_available_ticks - + cabi->cpu_period_used_ticks; + + /* check */ + cabi_debug_state(cabi); + cabi_debug_ticks(cabi); + + /* set new state */ + cabi->cpu_state = CABI_IS_NULL; + + + if (left <= 0) { + cabi->cpu_state |= CABI_IS_DEPLETED; + + /* check state */ + cabi_debug_state (cabi); + } + break; + } +} + + +#ifdef CONFIG_PROC_FS +/* this is test global variables. */ +int count = 0; +int gc =0; + +int +cabi_account_read_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + cpu_tick_data_t used_cpu_time; + cpu_capacity_t ave, cur, prv; /* unsigned long */ + unsigned long rem; + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + ENTER; + + /* check before load */ + cabi_debug_ticks (cabi); + + /* set tick */ + used_cpu_time = TICK2USEC(&cabi->cpu_period_used_ticks); + + /* set capacity */ + cur = capacity_of (cabi->cpu_period_used_ticks, + cabi->cpu_period_ticks); + + /* check prev */ + cabi_debug_tick (cabi->cpu_period_prev_used_ticks); + + /* set capacity */ + prv = capacity_of (cabi->cpu_period_prev_used_ticks, + cabi->cpu_period_ticks); + + /* set total utils */ + if (cabi->cpu_average.total_count) { + /* + * ave : %ul + * total_utils : %ull + * total_count : %ul + */ + ave = (unsigned long) div_long_long_rem ( + (unsigned long long) cabi->cpu_average.total_utils, + (unsigned long) cabi->cpu_average.total_count,&rem); + + if(cabi->cpu_average.total_utils > 1000000000) { + /* this is not good solution, FIX ME */ + cabi->cpu_average.history[gc++] = ave; + cabi->cpu_average.total_utils = 0; + cabi->cpu_average.total_count = 0; + } + + } else { + ave = cur; + } + + /* 1st line: utilization statics */ + /* reseved, previous, average, max, min */ + p += sprintf(p, "%lu.%04lu ", + CAPACITY_INT(cabi->cpu_capacity), + CAPACITY_FRAC(cabi->cpu_capacity)); + + p += sprintf(p, "%lu.%04lu %lu.%04lu ", + CAPACITY_INT(prv), CAPACITY_FRAC(prv), + CAPACITY_INT(ave), CAPACITY_FRAC(ave)); + + p += sprintf(p, "%lu.%04lu ", + CAPACITY_INT(cabi->cpu_max_utilization), + CAPACITY_FRAC(cabi->cpu_max_utilization)); + + p += sprintf(p, "%lu.%04lu \n", + CAPACITY_INT(cabi->cpu_min_utilization), + CAPACITY_FRAC(cabi->cpu_min_utilization)); + + /* 2nd line: current CPU usage + * used available requested */ + + p += sprintf(p, "%llu %lu %lu\n", + used_cpu_time, + TICK2USEC(&cabi->cpu_period_available_ticks), + TICK2USEC(&cabi->cpu_time_ticks)); + /* debug */ + cabi_debug_ticks (cabi); + + /* 3rd line: count of replenishment */ + p += sprintf(p, "%lu\n", cabi->cpu_average.total_count); + + /* 4th line: account object id */ + p += sprintf(p, "%lu\n", cabi->cabi_id); + + /* 5th line: process id */ + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = list_entry(proc_list, struct rs_proc_list, + rs_proc_list); + p += sprintf(p, "%d ", rs_proc->rs_proc_pid); + /* next element */ + proc_list = proc_list->next; + } + p += sprintf(p, "\n"); + + return (p - buf); +} + +int +cabi_account_read_bindpid_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list; + + /* find rs_proc */ + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = list_entry(proc_list, struct rs_proc_list, + rs_proc_list); + p += sprintf(p, "%d\n", rs_proc->rs_proc_pid); + /* next element */ + proc_list = proc_list->next; + } + return (p - buf); +} + +int +cabi_account_status_proc(char *buf) +{ + char *p = buf; + + /* cabi ticks per second, CPU capacity taken for accounts */ + p += sprintf(p, "%lu\n", + (unsigned long) cabi_cpu_ticks_per_second); + + return (p - buf); +} + +int +cabi_account_base_status_proc(char *buf) +{ + return 0; +} +#endif /* CONFIG_PROC_FS */ diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_cyclic.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_cyclic.c --- ./linux-2.6.18.1/drivers/cabi/cabi_cyclic.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_cyclic.c 2007-06-17 00:01:53.000000000 +0900 @@ -0,0 +1,332 @@ +/* + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University + * Nakajima Laboratory. + * + * 2007 Midori Sugaya + * + */ + +#include +#include +#include + +/* + * -------------------------------------------------------------- + * Policy : Default cyclic executive + * --------------------------------------------------------------- + * Status : RUNNING running when the replenish timer expires. + * : DEPLETED depleted when the replenish timer expires, + * : NULL + * --------------------------------------------------------------- + * Operation : BLOCK change status of the operation + * : SIGNAL change status of the operation + * --------------------------------------------------------------- + * Priority : Not control, use user defined priority + * --------------------------------------------------------------- + */ + +int is_running = 0; +void cyc_replenish (cabi_account_t); +void cyc_replenish_capacity (cabi_account_t); +void cyc_account_status_in (cabi_account_t); +void cyc_account_status_out (cabi_account_t); +void cyc_statistic_calculation (cabi_account_t); +void cyc_replenish_operation (cabi_account_t); +void cyc_isr (cabi_account_t); +void cyc_isr_operation (cabi_account_t); + +struct cabi_account_operations cyclic_ops = { + .replenish = cyc_replenish, + .isr = cyc_isr, + .isr_operation = cyc_isr_operation, +}; + +void +cyc_replenish (cabi_account_t cabi) +{ + + ENTER; + cyc_account_status_in(cabi); + cyc_statistic_calculation (cabi); + cyc_replenish_capacity(cabi); + cyc_account_status_out (cabi); + EXIT; + +} + +void +cyc_replenish_capacity (cabi_account_t cabi) +{ + /* debug */ + cabi_debug_ticks(cabi); + cabi_debug_info(cabi); + + /* reset the used ticks */ + cabi->cpu_period_used_ticks = 0; +} + +void +cyc_stop_account (cabi_account_t cabi) +{ + cpu_tick_data_t now; + + ENTER; + cabi_rdticks(&now); + cabi_stop_account(cabi, &now); + is_running++; + EXIT; +} +void +cyc_account_status_in (cabi_account_t cabi) +{ + + ENTER; + switch (cabi->cpu_state) { + case CABI_IS_NULL: + /* 00 : no bind process */ + CABI_DBG; + cabi_debug_state(cabi); + break; + case CABI_IS_RUNNING: + /* 01 : passed the period */ + CABI_DBG; + cabi_debug_state(cabi); + cyc_stop_account(cabi); + break; + case CABI_IS_DEPLETED: + /* 10 : correctly accounted */ + CABI_DBG; + cabi_debug_state(cabi); + break; + case CABI_IS_RUNNING|CABI_IS_DEPLETED: + /* 11 : fist time to account */ + CABI_DBG; + cabi_debug_state(cabi); + cyc_stop_account(cabi); + break; + default: + /* it should not be */ + CABI_DBG; + cabi_debug_state(cabi); + break; + } + + /* it should be changed to the initial status, CABI_IS_NULL. */ + cabi->cpu_state &= ~CABI_IS_DEPLETED; + + EXIT; +} + +void +cyc_replenish_operation (cabi_account_t cabi) +{ + + switch (cabi->pm.operation) { + case OP_BLOCK: + cabi_debug("[op_block] op: %d\n", + cabi->pm.operation); + cabi->opt_state = CABI_UNBLOCK; + wake_up(&cabi->depleted_wait); + break; + case OP_SIGNAL: + cabi_debug("[op_signal] op: %d\n", + cabi->pm.operation); + break; + default: + break; + } +} + +void +cpu_time_replenish_init (cabi_account_t cabi) +{ + + cabi->cpu_period_available_ticks = cabi->cpu_time_ticks; +} + +int bonus; + +void +cyc_account_status_out (cabi_account_t cabi) +{ + + unsigned long long avail = cabi->cpu_period_available_ticks; + unsigned long long used = cabi->cpu_period_prev_used_ticks; + unsigned long long cpu_time = cabi->cpu_time_ticks; + + ENTER; + + if (avail > 0){ + + switch (cabi->pm.rep_policy) { + case REP_SOFT: + CABI_DBG; + if (avail != cabi->cpu_time_ticks) { + cabi_debug_ticks (cabi); + cpu_time_replenish_init(cabi); + } + break; + case REP_HARD: + CABI_DBG; + if (bonus) { + bonus = ~bonus; + cpu_time_replenish_init(cabi); + break; + } else { + bonus++; + if (cpu_time > used) { + CABI_DBG; + /* used less than the capacity */ + cpu_time_replenish_init(cabi); + cabi->cpu_period_available_ticks + += (cpu_time - used); + cabi_debug_avail_ticks (cabi); + } else if (cpu_time < used) { + CABI_DBG; + /* used more than the capacity */ + cpu_time_replenish_init(cabi); + cabi->cpu_period_available_ticks + -= (used - cpu_time); + cabi_debug_avail_ticks (cabi); + } else { + CABI_DBG; + /* equal to avail and used */ + cabi_debug_avail_ticks (cabi); + } + } + break; + default: + /* if not set anything, this path is taken. */ + break; + } + cyc_replenish_operation(cabi); + + } else { + CABI_DBG; + cabi_debug_avail_ticks(cabi); + cpu_time_replenish_init(cabi); + + if (is_running) + cabi_start_account(cabi); + } + + +} + +void +cyc_statistic_calculation(cabi_account_t cabi) +{ + + cpu_capacity_t c; + + ENTER; + + /* update statistics */ + cabi->cpu_period_prev_used_ticks = cabi->cpu_period_used_ticks; + cabi->cpu_total_used_ticks += cabi->cpu_period_used_ticks; + + /* check capacity */ + c = capacity_of(cabi->cpu_period_used_ticks, + cabi->cpu_period_ticks); + + /* debug */ + cabi_debug_capacity(c); + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + + /* capacity is exceed the max utilization */ + cabi_debug_capacity(c); + + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + + cabi->cpu_min_utilization = c; + + /* capacity: less than the min util */ + cabi_debug_capacity(c); + + } + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + + /* capacity is exceed the max utilization */ + cabi_debug_capacity(c); + + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + + cabi->cpu_min_utilization = c; + + /* capacity: less than the min util */ + cabi_debug_capacity(c); + } + + /* summation for average */ + cabi->cpu_average.total_utils += c; + cabi->cpu_average.total_count++; + + EXIT; +} + +extern cabi_account_t cabi_current_account; +void cyc_isr (cabi_account_t); +void cyc_isr_operation (cabi_account_t); + + +void +cyc_isr (cabi_account_t cabi) +{ + + ENTER; + if (cabi_account_depleted(cabi)) + cyc_isr_operation(cabi); + + EXIT; +} + +void +cyc_isr_operation (cabi_account_t cabi) +{ + + ENTER; + switch (cabi->pm.operation) { + case OP_BLOCK: + CABI_DBG; + cabi->opt_state = CABI_BLOCKED; + cabi->block_count++; + cabi_account_sleep_on(cabi); + break; + case OP_SIGNAL: + CABI_DBG; + if (cabi->opt_state != CABI_SIGNAL) + cabi->opt_state = CABI_SIGNAL; + if (!CABI_SIGFLAG(cabi)) { + if (!cabi->signal_block) { + cabi_send_signal( + cabi, current->pid, + CABI_SIGNUM(cabi)); + } + } else { + if (!cabi->signal_block) { + cabi_send_signal( + cabi, CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + } + } + break; + default: + cabi_current_account = NULL_ACCOUNT; + CABI_DBG; + cabi_debug ("cabi_ret_with_reschedule:" + "cabi(0x%x) operation(%d)\n", + (int) cabi, cabi->pm.operation); + + break; + } + EXIT; +} + diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_debug.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_debug.c --- ./linux-2.6.18.1/drivers/cabi/cabi_debug.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_debug.c 2007-06-17 00:01:30.000000000 +0900 @@ -0,0 +1,649 @@ +/* + * linux/drivers/cabi/cabi_debug.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University + * Nakajima Laboratory. + * + * 2007 Midori Sugaya + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * For test + */ +int cabi_len = 0; +int cabi_debug_counter = 0; +unsigned long *start_address; +int cabi_dump_flag = 0; +int cabi_mask = 0x3ff; +int serial_number = 0; +/* + * 0x3f (63) + * 0x7f (127) + * 0xff (255) + * 0x1ff (511) + * 0x3ff (1023) + * 0xfff (4095) + * 0x13ff (5120) 1024*5 + */ +struct cabi_dump_struct +{ + int counter; + int logid; + unsigned long long tsc_time; + pid_t pid; + unsigned long cabi_id; +}; +struct cabi_dump_struct *cs; + +unsigned long buffer_counter = 0; +unsigned long serial_counter = 0; + +int cabi_dump_init (void) +{ + + cs = malloc ((cabi_mask+1)* (sizeof (struct cabi_dump_struct))); + bzero(cs, (cabi_mask+1) * (sizeof (struct cabi_dump_struct))); + buffer_counter = 0; + + if (!cs) { + printk ("Can not allocate memory!\n"); + return -1; + } + + cabi_dump_flag = 1; + return 0; +} + +void cabi_dump (int logid) +{ + + unsigned long long now; + unsigned long flag; + + if (cabi_dump_flag) { + cabi_spin_lock (flag); + (cs + buffer_counter)->counter = serial_counter++; + (cs + buffer_counter)->logid = logid; + cabi_eval_rdtsc(&now); + (cs + buffer_counter)->tsc_time = now; + (cs + buffer_counter)->pid = 0; + (cs + buffer_counter)->cabi_id = 0; + + buffer_counter++; + buffer_counter &= cabi_mask; + cabi_spin_unlock (flag); + } +} + +void cabi_dump_sched (int logid, struct task_struct *tsk) +{ + + unsigned long long now; + unsigned long flag; + + cabi_account_t cabi = TASK_ACCOUNT(tsk); + + + if (cabi_dump_flag) { + cabi_spin_lock (flag); + (cs + buffer_counter)->counter = serial_counter++; + (cs + buffer_counter)->logid = logid; + cabi_eval_rdtsc(&now); + (cs + buffer_counter)->tsc_time = now; + (cs + buffer_counter)->pid = tsk->pid; + + if (cabi == NULL) { + (cs + buffer_counter)->cabi_id = 0; + } else { + (cs + buffer_counter)->cabi_id = cabi->cabi_id; + } + buffer_counter++; + buffer_counter &= cabi_mask; + cabi_spin_unlock (flag); + } +} + +void cabi_dump_end (void) +{ + unsigned long flag; + cabi_dump_flag = 0; + buffer_counter = 0; + + cabi_spin_lock(flag); + free (cs); + cabi_spin_unlock(flag); + + +} +void cabi_dump_ex (int logid, struct task_struct *tsk, + cabi_account_t cabi) +{ + + unsigned long long now; + + + cabi_eval_rdtsc(&now); + + if (cabi_dump_flag) { + (cs + buffer_counter)->counter = serial_counter++; + (cs + buffer_counter)->logid = logid; + (cs + buffer_counter)->tsc_time = now; + if (tsk) + (cs + buffer_counter)->pid = tsk->pid; + else + (cs + buffer_counter)->pid = 0; + if (cabi) + (cs + buffer_counter)->cabi_id = cabi->cabi_id; + else + (cs + buffer_counter)->cabi_id = 0; + + buffer_counter++; + buffer_counter &= cabi_mask; + } +} + +unsigned long read_counter; +void cabi_dump_read (int flag) +{ + + unsigned long temp_counter; + unsigned long local_counter; + unsigned long flags; + int i; + + cabi_dump_flag = 0; + local_counter = 0; + + if (flag) { + temp_counter = buffer_counter; + temp_counter &= cabi_mask; + printk("logid = %d\n", (cs+temp_counter)->logid); + + if ((cs + temp_counter)->logid == 0) { + read_counter = 0; + } else { + read_counter = buffer_counter; + } + } + cabi_spin_lock(flags); + printk ("CABI-DUMP: LOOP %d\n", cabi_mask+1); + //do { + for (i=0; i< 127; i++) { + local_counter++; + + if ((cs+read_counter)->pid) { + printk ("CABI-DMPRD:%lu %d %d %llu %d %lu\n", + local_counter, + (cs + read_counter)->counter, + (cs + read_counter)->logid, + (cs + read_counter)->tsc_time, + (cs + read_counter)->pid, + (cs + read_counter)->cabi_id); + } else { + printk ("CABI-DMPRD:%lu %d %d %llu \n", + local_counter, + (cs + read_counter)->counter, + (cs + read_counter)->logid, + (cs + read_counter)->tsc_time); + } + read_counter++; + read_counter &= cabi_mask; + } + + //} while (read_counter != buffer_counter); + + cabi_spin_unlock(flags); +} + + + +void +__debug_timespecs (struct timespec *c, struct timespec *t) +{ + cabi_debug("[debug_timespec] c (%lu %lu) t (%lu %lu)\n", + (unsigned long)c->tv_sec, + (unsigned long)c->tv_nsec, + (unsigned long)t->tv_sec, + (unsigned long)t->tv_nsec); +} + +void +cabi_debug_timespecs (struct timespec *c, struct timespec *t) +{ + __debug_timespecs (c,t); +} + +void +cabi_debug_timespec (struct timespec *t) +{ + + cabi_debug ("[debug_timespec] t (%lu %lu)\n", + (unsigned long)t->tv_sec, + (unsigned long)t->tv_nsec); +} + + +void cabi_debug_ct(cpu_capacity_quad_t qc, cpu_capacity_quad_t qt) +{ + cabi_debug("[debug_ct] qc %llu qt %llu\n", qc, qt); +} + +void +cabi_debug_capacity (cpu_capacity_t capacity) +{ + cabi_debug ("[capacity] capacity %lu.%02lu \n", + CAPACITY_INT(capacity), + CAPACITY_FRAC(capacity)); +} + + +void +cabi_debug_sig_param (cabi_account_t cabi) +{ + cabi_debug ("[cabi_sig_param] signal : pid %d sig %d flag %d\n", + (int) CABI_SIGPID(cabi), (int) CABI_SIGNUM(cabi), + (int) CABI_SIGFLAG(cabi)); +} + +void +cabi_sanity_check_euid (struct task_struct *tsk) +{ + + cabi_debug("cabi_create: Permission denied. EUID [%d], UID [%d]\n", + tsk->euid, tsk->uid); +} + +int +pid_check (pid_t pid) +{ + if (pid < 0) { + cabi_debug("[bind_pid]: invalid pid (%d)\n", + (int) pid ); + return 1; + } + return 0; +} + +int +pgid_check (pid_t pgid) +{ + if (pgid == 0 || pgid < 0) { + cabi_debug("[bind_pgid]: invalid pgid %d.\n", + (int) pgid); + return 1; + } + return 0; +} + +int +cabi_id_check (unsigned long cabi_id) +{ + if (cabi_id == 0 || cabi_id == OVERLOAD_CABI_ID) { + cabi_debug("invalid cabi id %d\n", + (int) cabi_id); + return 1; + } + return 0; +} + +void +bind_pid_error (pid_t pid) +{ + cabi_debug ("[bind_pid] error invalid pid(%d)\n", pid); +} + + +void +cabi_account_attached(void) +{ + + cabi_debug("account_attach_process: account already " + "attached pid(%d) cabi(0x%x) [%d]\n", + current->pid, (int) TASK_ACCOUNT(current), + (int) TASK_ACCOUNT(current)->cabi_id); +} + +int +cabi_sanity_check_ucabi (struct cabi_uaccount *user_cabi) +{ + + ENTER; + + + if (user_cabi->cpu_time.tv_sec <= 0 && + user_cabi->cpu_time.tv_nsec <= 0) { + cabi_debug("cpu_time sec %lu nsec %lu\n", + user_cabi->cpu_time.tv_sec, + user_cabi->cpu_time.tv_nsec); + return CABI_EINVAL; + } + + CABI_DBG; + if (user_cabi->cpu_period.tv_sec <= 0 && + user_cabi->cpu_period.tv_nsec <= 0) { + cabi_debug("period sec %lu nsec %lu\n", + user_cabi->cpu_period.tv_sec, + user_cabi->cpu_period.tv_nsec); + return CABI_EINVAL; + } + + CABI_DBG; + if (user_cabi->pm.operation == OP_BLOCK) { + if (user_cabi->pm.operation <= OP_NONE || + user_cabi->pm.operation >= OP_UNKNOWN) + return CABI_EINVAL; + + CABI_DBG; + if (user_cabi->pm.bind_proc_type < BIND_NORMAL_PROC || + user_cabi->pm.bind_proc_type > BIND_IDLE_PROC) + return CABI_EINVAL; + } + + if (user_cabi->pm.operation == CABI_SIGNAL) { + CABI_DBG; + if (user_cabi->pm.operation == OP_SIGNAL) { + if (user_cabi->pm.cabi_signal.pid < 0) + return CABI_EINVAL; + if (user_cabi->pm.cabi_signal.sig < 0 || + user_cabi->pm.cabi_signal.sig > 32) + return CABI_EINVAL; + } + } + EXIT; + return CABI_SUCCESS; +} + +int +cabi_sanity_check_operation (struct cabi_uaccount *ucabi) +{ + ENTER; + switch (ucabi->pm.operation) { + case OP_BLOCK: + CABI_DBG; + if (ucabi->pm.operation != OP_BLOCK) + return -1; + break; + case OP_SIGNAL: + CABI_DBG; + if (ucabi->pm.operation != OP_SIGNAL) + return -1; + + /* check signal validatations */ + if (!ucabi->pm.cabi_signal.pid) { + ucabi->pm.cabi_signal.flag = CABI_SEND_DEFL; + } else { + ucabi->pm.cabi_signal.flag = CABI_SEND_PID; + } + if (!ucabi->pm.cabi_signal.sig) { + /* if signal number is null, set default + signal which will do nothing. */ + ucabi->pm.operation = OP_NONE; + } + break; + default: + break; + } + EXIT; + + return 0; +} + +int +cabi_sanity_check_timespec_c_and_t ( + struct timespec *cpu_time, + struct timespec *cpu_period) +{ + + long time_sec, time_nsec, period_sec, period_nsec; + + ENTER; + + /* Initialize and check execution time parameter */ + time_sec = time_nsec = 0; + time_sec = cpu_time->tv_nsec / NANOSEC; + time_nsec = cpu_time->tv_nsec - time_sec * NANOSEC; + + if (time_sec > (long)(CABI_TIME_SEC_MAX - cpu_time->tv_sec)) { + cabi_debug("cpu_time is over %ld\n", time_sec); + return CABI_EINVAL; + } + time_sec += cpu_time->tv_sec; + + /* Initizalize and check the period parameter */ + period_sec = period_nsec = 0; + period_sec = cpu_period->tv_nsec / NANOSEC; + period_nsec = cpu_period->tv_nsec - period_sec * NANOSEC; + + + if (period_sec > (long)(CABI_TIME_SEC_MAX - cpu_period->tv_sec)) { + cabi_debug ("cpu_period is over max %ld\n", period_sec); + return CABI_EINVAL; + } + period_sec += cpu_period->tv_sec; + + + if (time_sec > period_sec) { + cabi_debug ("time_sec > period_sec error!.\n"); + return CABI_EINVAL; + } else if (time_sec == period_sec) { + if (time_nsec > period_nsec) { + cabi_debug ("time_nsec > period_nsec error.\n"); + return CABI_EINVAL; + + } + } + EXIT; + return CABI_SUCCESS; +} + +int +cabi_sanity_check_overload_id (void) +{ + + cabi_account_t cabi; + + if ((cabi = search_cabi(OVERLOAD_CABI_ID)) != NULL) { + cabi_debug ("[%d] idle cabi_id : %d\n", __LINE__, + (int)cabi->cabi_id); + return CABI_EINVAL; + } + return CABI_SUCCESS; +} + +int +cabi_sanity_check_sigoperation (struct cabi_uaccount *user_cabi) +{ + if (user_cabi->pm.operation != OP_SIGNAL) { + cabi_debug("invalid operation \n"); + return CABI_EINVAL; + } + cabi_debug ("[sys_create] idle cabi act : %d\n", + user_cabi->pm.operation); + return CABI_SUCCESS; +} + +void +cabi_sanity_check_parameter_to_copy (struct timespec *c, + struct timespec *t, struct cpu_param *p) +{ + cabi_debug ("[sys_create: %d] c(%d), t(%d), operation(%x)" + " bind_proc_type (%x)\n", + __LINE__, + (int) c->tv_nsec, + (int) t->tv_nsec, + p->operation, + p->bind_proc_type); +} + + +/* cabi account attach */ +void cabi_debug_info (cabi_account_t cabi) +{ + CABI_DBG; + cabi_debug("cabi %x, id %lu\n", + (int)cabi, cabi->cabi_id); +} + +void cabi_debug_state (cabi_account_t cabi) +{ + CABI_DBG; + cabi_debug ("cabi_cpu_state 0x%x \n", (int) cabi->cpu_state); +} + +void cabi_debug_detach (struct rs_proc_list *rs_proc) +{ + CABI_DBG; + cabi_debug("[detach] rs_proc(0x%x) pid (%d)\n", + (int) rs_proc, rs_proc->rs_proc_pid); +} + +/* replenish */ +void cabi_debug_ticks (cabi_account_t cabi) +{ + CABI_DBG; + cabi_debug ("[ticks] used %llu period %llu avail %llu cpu_time %llu\n", + cabi->cpu_period_used_ticks, + cabi->cpu_period_ticks, + cabi->cpu_period_available_ticks, + cabi->cpu_time_ticks); +} + +void cabi_debug_avail_ticks (cabi_account_t cabi) +{ + cabi_debug ("[avail_ticks] used %llu avail %llu cpu_time %llu\n", + cabi->cpu_period_used_ticks, + cabi->cpu_period_available_ticks, + cabi->cpu_time_ticks); +} + +void cabi_debug_tick (unsigned long long tick) +{ + cabi_debug("tick %llu\n", tick); +} + +/* cabi_sched.c */ +void cabi_debug_entities (cabi_account_t cabi01, + cabi_account_t cabi02) +{ + cabi_debug("cabi %x cabi %x\n", + (int) cabi01, (int) cabi02); +} + +/* cabi_signal.c */ +void cabi_debug_signal_pid (int pid) +{ + cabi_debug ("cabi_send_signal: invalid pid (%d).\n", pid); + cabi_debug ("No received process. (%d)\n", pid); +} + +void cabi_debug_signal_attrs (int pid, int sig, struct task_struct *tsk) +{ + cabi_debug ("cabi_send_signal: pid %d sig %d \n", pid, sig); + cabi_debug ("pid %d status %d\n", + (int) tsk->pid, (int)tsk->state); + cabi_debug ("signal_struct: count %d\n", + (int)tsk->signal->count.counter); +} + +/* cabi_timer.c */ +void cabi_debug_times (struct timer_list *tmr, unsigned long jiffies) +{ + cabi_debug (" expires %lu, jiffies %lu)\n", + tmr->expires, jiffies); +} + +void cabi_debug_timer (struct timer_list *tmr) +{ + cabi_debug (" expires %lu \n", tmr->expires); +} + +/* kernel/sched.c */ +void cabi_debug_ksched (struct task_struct *prev, + struct task_struct *next) +{ + + cabi_account_t prev_cabi = TASK_ACCOUNT(prev); + cabi_account_t next_cabi = TASK_ACCOUNT(next); + + /* check */ + if (prev_cabi) { + cabi_debug ("\n[ksched:01] prev_cabi[%d] prev[%d] next[%d]\n", + (int) prev_cabi->cabi_id, + prev->pid, next->pid); + } + if (next_cabi) { + cabi_debug ("[ksched:02]next_cabi[%d] prev[%d] next[%d]\n", + (int) next_cabi->cabi_id, + prev->pid, next->pid); + } + + if (prev->pid == 0 || next->pid == 0) { + if (TASK_ACCOUNT(prev) || TASK_ACCOUNT(next)) { + cabi_debug ("[ksched:03] prev[%d] next[%d]\n", + prev->pid, next->pid); + } + } +} + +/* cabi dsv */ + +void check_sched_param (struct rs_proc_list *rs_proc) +{ + + struct sched_param param; + sys_sched_getparam (rs_proc->rs_proc_task->pid, ¶m); + cabi_debug ("[boost:] pid %d prio %d\n", + rs_proc->rs_proc_task->pid, + (int) param.sched_priority); +} + +/* cabi_timer.c */ +void check_hrtimer_res (void) +{ + struct timespec res; + hrtimer_get_res (CLOCK_REALTIME, &res); + cabi_debug ("[rep_prcess] hrtimer_get_res %llu %llu \n", + (unsigned long long) res.tv_sec, + (unsigned long long) res.tv_nsec); +} + +void check_rep_expires (ktime_t expires) +{ + cabi_debug ("[rep_process] expire %llu\n", + expires.tv64); + +} + +void check_enf_expires (ktime_t expires) +{ + cabi_debug ("[enf_process] expire %llu\n", + expires.tv64); + +} + +void check_exstate (ktime_t expires, cabi_account_t cabi) +{ + cabi_debug ("[enf_start] expires %lld " + "state %d no-call hrtimer\n", + expires.tv64, cabi->cpu_state); +} + +void check_cancel (int ret) +{ + + cabi_debug ("[enf_cancel] hrtimer_try_to_cancel ret %d \n", ret); +} + diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_defsrv.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_defsrv.c --- ./linux-2.6.18.1/drivers/cabi/cabi_defsrv.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_defsrv.c 2007-05-04 22:39:26.000000000 +0900 @@ -0,0 +1,458 @@ +/* + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University + * / Nakajima Laboratory. MontaVista Software, Inc. + * + * Midori Sugaya + * + */ + +#include +#include +#include +#include +#include + +/* + * -------------------------------------------------------------- + * Policy : Defferrable Server Algorithm + * --------------------------------------------------------------- + * Status : RUNNING running when the replenish timer expires. + * : DEPLETED depleted when the replenish timer expires, + * : NULL + * --------------------------------------------------------------- + * Operation : BLOCK change status of the operation + * : SIGNAL change status of the operation + * : NONE nothing to do + * --------------------------------------------------------------- + * Priority : Boost until cpu_time + * --------------------------------------------------------------- + */ + +extern cabi_account_t cabi_current_account; +int dsv_is_running = 0; +extern int sched_setscheduler (struct task_struct *p, int policy, + struct sched_param *param); +extern spinlock_t cabi_lock; + + +/* prototypes */ +void dsv_replenish (cabi_account_t); +void dsv_replenish_capacity (cabi_account_t); +void dsv_account_status_in (cabi_account_t); +void dsv_account_status_out (cabi_account_t); +void dsv_statistic_calculation (cabi_account_t); +void dsv_replenish_operation (cabi_account_t); +void dsv_replenish_priority_boost (cabi_account_t); +void dsv_isr (cabi_account_t); +void dsv_isr_operation (cabi_account_t); +void dsv_isr_priority (cabi_account_t); +int setup_boost_priority (cabi_account_t); +int free_boost_priority (cabi_account_t); +int cabi_sched_setscheduler (pid_t,int policy, struct sched_param *); + + +/* operation table */ +struct cabi_account_operations dsv_ops = { + .replenish = dsv_replenish, + .isr = dsv_isr, + .isr_operation = dsv_isr_operation, + .isr_priority = dsv_isr_priority, +}; + +void +dsv_replenish (cabi_account_t cabi) +{ + ENTER; + dsv_account_status_in(cabi); + dsv_statistic_calculation (cabi); + dsv_replenish_capacity(cabi); + dsv_account_status_out (cabi); + EXIT; +} + +void +dsv_replenish_capacity (cabi_account_t cabi) +{ + ENTER; + + /* debug */ + cabi_debug_ticks(cabi); + cabi_debug_info(cabi); + + /* reset the used ticks */ + cabi->cpu_period_used_ticks = 0; + EXIT; +} + +void +dsv_stop_account (cabi_account_t cabi) +{ + cpu_tick_data_t now; + + ENTER; + cabi_rdticks(&now); + cabi_stop_account(cabi, &now); + dsv_is_running++; + EXIT; +} +void +dsv_account_status_in (cabi_account_t cabi) +{ + + ENTER; + /* it should be changed to the initial status, CABI_IS_NULL. */ + dsv_stop_account(cabi); + cabi->cpu_state &= ~CABI_IS_DEPLETED; + EXIT; +} + + + + +void +dsv_replenish_operation (cabi_account_t cabi) +{ + ENTER; + + /* even if there are set any operation, if policy is dsv, + one operation should be done. */ + + switch (cabi->pm.operation) { + case OP_BLOCK: + cabi_debug("[op_block] op: %d\n", + cabi->pm.operation); + break; + case OP_SIGNAL: + cabi_debug("[op_signal] op: %d\n", + cabi->pm.operation); + break; + case OP_NONE: + cabi_debug("[op_boost] op: %d\n", + cabi->pm.operation); + break; + default: + break; + } + EXIT; +} + +void +dsv_cpu_time_replenish_init (cabi_account_t cabi) +{ + + cabi->cpu_period_available_ticks = cabi->cpu_time_ticks; +} + +extern int bonus; + +void +dsv_account_status_out (cabi_account_t cabi) +{ + + unsigned long long avail = cabi->cpu_period_available_ticks; + unsigned long long used = cabi->cpu_period_prev_used_ticks; + unsigned long long cpu_time = cabi->cpu_time_ticks; + + ENTER; + + cabi->priority_boost = 1; + cabi->priority_depleted = 1; + + + if (avail > 0){ + switch (cabi->pm.rep_policy) { + case REP_SOFT: + CABI_DBG; + if (avail != cabi->cpu_time_ticks) { + cabi_debug_ticks (cabi); + dsv_cpu_time_replenish_init(cabi); + } + break; + case REP_HARD: + CABI_DBG; + if (bonus) { + bonus = ~bonus; + dsv_cpu_time_replenish_init(cabi); + break; + } else { + bonus++; + if (cpu_time > used) { + CABI_DBG; + /* used less than the capacity */ + dsv_cpu_time_replenish_init(cabi); + cabi->cpu_period_available_ticks + += (cpu_time - used); + cabi_debug_avail_ticks (cabi); + } else if (cpu_time < used) { + CABI_DBG; + /* used more than the capacity */ + dsv_cpu_time_replenish_init(cabi); + cabi->cpu_period_available_ticks + -= (used - cpu_time); + cabi_debug_avail_ticks (cabi); + } else { + CABI_DBG; + /* equal to avail and used */ + cabi_debug_avail_ticks (cabi); + } + } + break; + default: + /* if not set anything, + this path is taken. */ + break; + } + dsv_replenish_operation(cabi); + + } else { + CABI_DBG; + cabi_debug_avail_ticks(cabi); + dsv_cpu_time_replenish_init(cabi); + } + + if (dsv_is_running) { + cabi_start_account(cabi); + } + + + + EXIT; +} + +void +dsv_statistic_calculation(cabi_account_t cabi) +{ + + cpu_capacity_t c; + ENTER; + + /* update statistics */ + cabi->cpu_period_prev_used_ticks + = cabi->cpu_period_used_ticks; + cabi->cpu_total_used_ticks + += cabi->cpu_period_used_ticks; + + /* check capacity */ + c = capacity_of(cabi->cpu_period_used_ticks, + cabi->cpu_period_ticks); + + /* debug */ + cabi_debug_capacity(c); + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + + /* capacity is exceed the max utilization */ + cabi_debug_capacity(c); + + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + + cabi->cpu_min_utilization = c; + + /* capacity: less than the min util */ + cabi_debug_capacity(c); + + } + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + + /* capacity is exceed the max utilization */ + cabi_debug_capacity(c); + + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + + cabi->cpu_min_utilization = c; + + /* capacity: less than the min util */ + cabi_debug_capacity(c); + } + + /* summation for average */ + cabi->cpu_average.total_utils += c; + cabi->cpu_average.total_count++; + + EXIT; +} + + +void +dsv_isr (cabi_account_t cabi) +{ + + ENTER; + dsv_isr_operation(cabi); + EXIT; +} + +void +dsv_isr_operation (cabi_account_t cabi) +{ + + ENTER; + /* whenever the operation is set or not, we set the + same operation for the process */ + + switch (cabi->pm.operation) { + case OP_NONE: + CABI_DBG; + break; + case OP_BLOCK: + CABI_DBG; + break; + case OP_SIGNAL: + CABI_DBG; + if (cabi->opt_state != CABI_SIGNAL) + cabi->opt_state = CABI_SIGNAL; + if (!CABI_SIGFLAG(cabi)) { + if (!cabi->signal_block) { + cabi_send_signal( + cabi, current->pid, + CABI_SIGNUM(cabi)); + } + } else { + if (!cabi->signal_block) { + cabi_send_signal( + cabi, CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + } + } + default: + cabi_current_account = NULL_ACCOUNT; + break; + } + dsv_isr_priority (cabi); + + EXIT; +} + +void +dsv_isr_priority (cabi_account_t cabi) +{ + + ENTER; + CABI_DBG; + + /* if this function called from the replenish_account, + the priority_boost bit is set. So we setup the + priority boost */ + if (cabi->priority_boost) { + setup_boost_priority(cabi); + cabi->priority_boost = 0; + + } + + /* if cabi is depleted, the flag is set + at fist time */ + if (cabi->priority_depleted) { + if (cabi->cpu_state & CABI_IS_DEPLETED) { + free_boost_priority (cabi); + cabi->priority_depleted = 0; + } + + } + EXIT; +} + +int +free_boost_priority (cabi_account_t cabi) +{ + + struct sched_param param = { .sched_priority = 0 }; + struct rs_proc_list *rs_proc; + struct list_head *proc_list; + + ENTER; + + cabi_debug_state(cabi); + if (!list_empty(&cabi->cpu_proc_list)) { + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + rs_proc = list_entry (proc_list, + struct rs_proc_list, rs_proc_list); + + /* if there are tasks in the list + * set static priority + */ + if(rs_proc->rs_proc_task) { + //check_sched_param (rs_proc->rs_proc_task); + cabi_sched_setscheduler( + rs_proc->rs_proc_task->pid, + SCHED_NORMAL, ¶m); + } + proc_list = proc_list->next; + } + } + EXIT; + return 0; + +} + +int +cabi_sched_setscheduler(pid_t pid, + int policy, struct sched_param *param) +{ + struct task_struct *p; + int retval; + + ENTER; + + if (!param || pid < 0) + return -EINVAL; + + p = __cabi_find_process_by_pid (pid); + if (!p) { + read_unlock_irq(&tasklist_lock); + return -ESRCH; + } + + retval = sched_setscheduler(p, policy, param); + + EXIT; + + return retval; +} + + +int +setup_boost_priority (cabi_account_t cabi) +{ + + struct rs_proc_list *rs_proc = NULL; + struct list_head *proc_list = NULL; + struct sched_param param; + + ENTER; + + if (!list_empty(&cabi->cpu_proc_list)) { + + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + rs_proc = list_entry (proc_list, + struct rs_proc_list, rs_proc_list); + /* if there are tasks in the list + * set static priority + */ + if(rs_proc->rs_proc_task) { + + //check_sched_param (rs_proc->rs_proc_task); + + param.sched_priority = + CABI_RT_MAX_PRIORITY; + + cabi_sched_setscheduler ( + current->pid, + SCHED_FIFO, ¶m); + } + proc_list = proc_list->next; + } + } + + EXIT; + return 0; +} + diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_init.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_init.c --- ./linux-2.6.18.1/drivers/cabi/cabi_init.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_init.c 2007-05-22 10:16:26.000000000 +0900 @@ -0,0 +1,154 @@ + /* + * linux/drivers/cabi/cabi_init.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +extern void cabi_account_init(void); +extern void cabi_proc_init(void); + +spinlock_t cabi_lock; +cpu_tick_data_t cabi_cpu_ticks_per_second; +cpu_tick_data_t cabi_cpu_ticks_per_jiffy; +cpu_tick_data_t cabi_timer_adjust; + +#ifdef CONFIG_X86 +#include +#define CHECK_TIME 5 +void +cabi_cpu_calibration_i386(void) +{ + + unsigned long first_jiffies, rem, ctps; + int i = CHECK_TIME; + cpu_tick_data_t begin, end, err, result; + + ENTER; + printk("CABI Calibrating cpu "); + + cabi_rdticks(&begin); + cabi_rdticks(&end); + err = end - begin; + +/* for debugging */ + /* wait for "start of" clock tick */ + first_jiffies = jiffies; + while (first_jiffies == jiffies) { + /* nothing */ + } + cabi_rdticks(&begin); + while (i-- > 0) { + first_jiffies = jiffies; + printk("."); + while (jiffies - first_jiffies < HZ) { + + } + } + cabi_rdticks(&end); + /* */ + + result = (end - begin - err); + cabi_cpu_ticks_per_second = result; + + /* use 64bit interface */ + ctps = div_long_long_rem(result, CHECK_TIME, &rem); + /* set the calculated result */ + cabi_cpu_ticks_per_second = (unsigned long long) ctps; + printk ("%llu\n", cabi_cpu_ticks_per_second); + + EXIT; +} +#else /* #ifdef CONFIG_X86 */ +void +cabi_cpu_calibration(void) +{ + printk("cabi initialize...\n"); + cabi_cpu_ticks_per_second = CABI_CLOCK; + { + cpu_tick_data_t t; + t = CABI_USECS_PER_JIFFY; + usec2tick(&t, &cabi_cpu_ticks_per_jiffy); + } +} +#endif /* #ifdef CONFIG_X86 */ + +void +cabi_init(void) +{ + spin_lock_init(&cabi_lock); + cabi_account_init(); +#ifdef CONFIG_X86 + cabi_cpu_calibration_i386(); +#else + cabi_cpu_calibration(); +#endif /* #ifdef CONFIG_X86 */ + +#ifdef CONFIG_PROC_FS + cabi_proc_init(); +#endif +} diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_isr.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_isr.c --- ./linux-2.6.18.1/drivers/cabi/cabi_isr.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_isr.c 2007-06-17 00:02:48.000000000 +0900 @@ -0,0 +1,193 @@ +/* + * linux/drivers/cabi/cabi_isr.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * Authors: Midori Sugaya, Hirotaka Ishikawa + * Please send bug-reports/suggestions/comments to doly@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_HIGH_RES_TIMERS +#include +#include +#endif + +extern cabi_account_t cabi_current_account; +/* + * Hooks + */ +int (*cabi_ret_with_reschedule_hook) (void); + +/* + * Checks + */ +void cabi_debug_current (cabi_account_t cabi_current) +{ + if (cabi_current) { + cabi_debug("current_account %x\n", + (int) cabi_current); + } +} + +void +cabi_account_sleep_on (cabi_account_t cabi) +{ + sleep_on (&cabi->depleted_wait); +} + +/* + * For "cabi_ret_with_reschedule_hook", cabi_ret_with_reschedule is called when + * a process exits from the kernel after processing a system call. + */ +asmlinkage int +cabi_ret_with_reschedule(void) +{ + + cabi_account_t cabi; + cabi_current_account = (cabi_account_t)TASK_ACCOUNT(current); + + /* debug */ + cabi_debug_current(cabi_current_account); + + /* set current account */ + if ((cabi = cabi_current_account)) { + cabi->ops->isr (cabi); + } + + + return 0; +} + +void +cabi_enable_isr(void) +{ + unsigned long flags; + + ENTER; + cabi_debug(" cabi_enable_isr %x reschedule_hook %x reschedule\n", + (int) cabi_ret_with_reschedule_hook, + (int) cabi_ret_with_reschedule); + + if (cabi_ret_with_reschedule_hook == &cabi_ret_with_reschedule) { + cabi_debug("cabi_enable_isr : hook already set.\n"); + return; + } + + cabi_spin_lock(flags); + { + /* install hooks */ + cabi_ret_with_reschedule_hook = &cabi_ret_with_reschedule; + + cabi_debug ("enable_isr: set ret_with_reschedule_hook %x\n" + " <== address %x (reschedule)\n", + (int) cabi_ret_with_reschedule_hook, + (int) cabi_ret_with_reschedule); + + /* start cabi timer */ + cabi_timer_start(); + } + cabi_spin_unlock(flags); + + EXIT; +} + +void +cabi_disable_isr(void) +{ + unsigned long flags; + + ENTER; + if (cabi_ret_with_reschedule_hook == (void *) 0) + return; + + cabi_spin_lock(flags); + { + /* remove hooks */ + cabi_ret_with_reschedule_hook = (void *) 0; + } + cabi_spin_unlock(flags); + EXIT; +} + + +#ifdef CONFIG_PROC_FS + +int +cabi_account_read_block_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + + if (cabi->pm.operation == OP_SIGNAL) { + p += sprintf(p, "%d\n%lu\n", cabi->opt_state, + cabi->signal_count); + } else { + p += sprintf(p, "%d\n%lu\n", cabi->opt_state, + cabi->block_count); + } + return (p - buf); +} + +#endif /* CONFIG_PROC_FS */ diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_overload.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_overload.c --- ./linux-2.6.18.1/drivers/cabi/cabi_overload.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_overload.c 2007-04-29 17:06:52.000000000 +0900 @@ -0,0 +1,432 @@ +/* + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University + * Nakajima Laboratory. MontaVista Software, Inc. + * + * Midori Sugaya + * + */ + +#include +#include +#include +#include + +/* + * -------------------------------------------------------------- + * Policy : Overload Monitoring + * --------------------------------------------------------------- + * Status : RUNNING running when the replenish timer expires. + * : DEPLETED depleted when the replenish timer expires, + * : NULL + * --------------------------------------------------------------- + * Operation : BLOCK change status of the operation + * : SIGNAL change status of the operation + * --------------------------------------------------------------- + * Priority : Not control, use user defined priority + * --------------------------------------------------------------- + */ + +extern int overload_cabi; +extern cabi_account_t cabi_current_account; +extern cabi_account_t cabi_current_overload_account; +int is_ovl_running; + +void ovl_replenish (cabi_account_t); +void ovl_replenish_capacity(cabi_account_t); +void ovl_account_status_in(cabi_account_t); +void ovl_account_status_out(cabi_account_t); +void ovl_statistic_calculation(cabi_account_t); +void ovl_replenish_operation (cabi_account_t); +void ovl_isr (cabi_account_t); +void ovl_isr_operation (cabi_account_t); + + +struct cabi_account_operations ovl_ops = { + .replenish = ovl_replenish, + .isr = ovl_isr, + .isr_operation = ovl_isr_operation, +}; + +void +ovl_replenish (cabi_account_t cabi) +{ + + ENTER; + ovl_account_status_in(cabi); + ovl_statistic_calculation (cabi); + ovl_replenish_capacity(cabi); + ovl_account_status_out (cabi); + EXIT; + +} + +void +ovl_replenish_capacity (cabi_account_t cabi) +{ + + ENTER; + /* debug */ + cabi_debug_ticks(cabi); + cabi_debug_info(cabi); + + /* reset the used ticks */ + cabi->cpu_period_used_ticks = 0; + EXIT; +} + +void +ovl_stop_account (cabi_account_t cabi) +{ + cpu_tick_data_t now; + + ENTER; + cabi_rdticks(&now); + cabi_stop_account(cabi, &now); + is_ovl_running++; + EXIT; +} +void +ovl_account_status_in (cabi_account_t cabi) +{ + + ENTER; + switch (cabi->cpu_state) { + case CABI_IS_NULL: + /* 00 : no bind process */ + CABI_DBG; + cabi_debug_state(cabi); + break; + case CABI_IS_RUNNING: + /* 01 : passed the period */ + CABI_DBG; + cabi_debug_state(cabi); + ovl_stop_account(cabi); + break; + case CABI_IS_DEPLETED: + /* 10 : correctly accounted */ + CABI_DBG; + cabi_debug_state(cabi); + break; + case CABI_IS_RUNNING|CABI_IS_DEPLETED: + /* 11 : fist time to account */ + CABI_DBG; + cabi_debug_state(cabi); + ovl_stop_account(cabi); + break; + default: + /* it should not be */ + CABI_DBG; + cabi_debug_state(cabi); + break; + } + + /* it should be changed to the initial status, CABI_IS_NULL. */ + cabi->cpu_state &= ~CABI_IS_DEPLETED; + + /* check overload condition */ + if (overload_cabi) + cabi_account_check_overload(); + + EXIT; +} + +void +ovl_replenish_operation (cabi_account_t cabi) +{ + ENTER; + + switch (cabi->pm.operation) { + case OP_BLOCK: + cabi_debug("[op_block] op: %d\n", + cabi->pm.operation); + cabi->opt_state = CABI_UNBLOCK; + wake_up(&cabi->depleted_wait); + break; + case OP_SIGNAL: + cabi_debug("[op_signal] op: %d\n", + cabi->pm.operation); + break; + default: + break; + } + EXIT; +} + +int ovl_bonus; + +void +ovl_account_status_out (cabi_account_t cabi) +{ + + unsigned long long avail = cabi->cpu_period_available_ticks; + unsigned long long used = cabi->cpu_period_prev_used_ticks; + unsigned long long cpu_time = cabi->cpu_time_ticks; + + ENTER; + if (avail > 0){ + switch (cabi->pm.rep_policy) { + case REP_SOFT: + CABI_DBG; + if (avail != cabi->cpu_time_ticks) { + cabi_debug_ticks (cabi); + cpu_time_replenish_init(cabi); + } + break; + case REP_HARD: + CABI_DBG; + if (ovl_bonus) { + ovl_bonus = ~ovl_bonus; + cpu_time_replenish_init(cabi); + break; + } else { + ovl_bonus++; + if (cpu_time > used) { + CABI_DBG; + /* used less than the capacity */ + cpu_time_replenish_init(cabi); + cabi->cpu_period_available_ticks + += (cpu_time - used); + cabi_debug_avail_ticks (cabi); + } else if (cpu_time < used) { + CABI_DBG; + /* used more than the capacity */ + cpu_time_replenish_init(cabi); + cabi->cpu_period_available_ticks + -= (used - cpu_time); + cabi_debug_avail_ticks (cabi); + } else { + CABI_DBG; + /* equal to avail and used */ + cabi_debug_avail_ticks (cabi); + } + } + break; + default: + /* if not set anything, this path is taken. */ + break; + } + ovl_replenish_operation(cabi); + + } else { + CABI_DBG; + cabi_debug_avail_ticks(cabi); + cpu_time_replenish_init(cabi); + + if (is_ovl_running) + cabi_start_account(cabi); + + } + EXIT; +} + + +void +ovl_statistic_calculation(cabi_account_t cabi) +{ + + cpu_capacity_t c; + + ENTER; + /* update statistics */ + cabi->cpu_period_prev_used_ticks = + cabi->cpu_period_used_ticks; + cabi->cpu_total_used_ticks += + cabi->cpu_period_used_ticks; + + /* check capacity */ + c = capacity_of(cabi->cpu_period_used_ticks, + cabi->cpu_period_ticks); + + /* debug */ + cabi_debug_capacity(c); + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + + /* capacity is exceed the max utilization */ + cabi_debug_capacity(c); + + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + + cabi->cpu_min_utilization = c; + + /* capacity: less than the min util */ + cabi_debug_capacity(c); + + } + + if (cabi->cpu_max_utilization < c) { + cabi->cpu_max_utilization = c; + + /* capacity is exceed the max utilization */ + cabi_debug_capacity(c); + + } else if (cabi->cpu_min_utilization > c + || cabi->cpu_min_utilization == 0) { + + cabi->cpu_min_utilization = c; + + /* capacity: less than the min util */ + cabi_debug_capacity(c); + } + + /* summation for average */ + cabi->cpu_average.total_utils += c; + cabi->cpu_average.total_count++; + + EXIT; +} + + +void +ovl_isr (cabi_account_t cabi) +{ + + ENTER; + if (cabi_account_overload(cabi)) + ovl_isr_operation(cabi); + + EXIT; +} + +void +ovl_isr_operation (cabi_account_t cabi) +{ + + ENTER; + switch (cabi->pm.operation) { + case OP_SIGNAL: + CABI_DBG; + if (cabi->opt_state != CABI_SIGNAL) + cabi->opt_state = CABI_SIGNAL; + if (!cabi->signal_block) { + cabi_send_signal( + cabi, CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + } + break; + default: + cabi_current_account = NULL_ACCOUNT; + CABI_DBG; + cabi_debug ("cabi_ret_with_reschedule:" + "cabi(0x%x) operation(%d)\n", + (int) cabi, cabi->pm.operation); + + break; + } + EXIT; +} + + + + +/* + * Name: capacity_overload + * + * This function return the new_qc value as a cpu time within + * a period. + */ +void +capacity_overload(struct timespec *c, struct timespec * t, + cpu_capacity_quad_t * overload_qc) +{ + + cpu_capacity_quad_t qc, qt, new_nano_qc; + cpu_capacity_t capacity; + + /* realculate requested capacity */ + qc = (c->tv_sec * NANOSEC) + c->tv_nsec; + qt = (t->tv_sec * NANOSEC) + t->tv_nsec; + + /* current requested capacity */ + capacity = capacity_of(qc, qt); + cabi_debug("[over] capacity(%lu.%02lu)\n", + CAPACITY_INT(capacity), CAPACITY_FRAC(capacity)); + + new_nano_qc = qt - qc; + cabi_debug("[over] new nano_qc %llu\n", + new_nano_qc); + overload_qc = &new_nano_qc; + cabi_debug("[over] overload_qc (%p),\n", + (cpu_capacity_quad_t *)overload_qc); + + +} + +int setup_overload_id (cabi_account_t cabi) +{ + + + if (!cabi_current_overload_account) { + /* + * set reserved id for the overload cabi + */ + cabi->cabi_id = OVERLOAD_CABI_ID; + cabi_current_overload_account = cabi; + + cabi_debug("[overload] overload id set %ld %x\n", + cabi->cabi_id, (int) cabi_current_overload_account); + + } else { + /* + * if there has been existed a overload cabi, + * return with error. + */ + cabi_debug("[ovl_set:02] overload already exist %x. error return.\n", + (int) cabi_current_overload_account); + + free (cabi); + return CABI_ERROR; + } + + return CABI_SUCCESS; +} + +int +cabi_account_check_overload(void) +{ + cabi_account_t cabi = NULL_ACCOUNT; + + /* search overload cabi */ + if (!cabi_current_overload_account) { + return CABI_ENOEXIST; + } else { + cabi = cabi_current_overload_account; + } + + if (cabi != cabi_current_account) + return CABI_ENOAVLE; + + /* compare the total used ticks with available ticks. */ + if (cabi->cpu_period_used_ticks < cabi->cpu_period_available_ticks) { + + cabi_debug("cabi_account_check_overload:" + " cabi(0x%x) used(%lu) < available(%lu)\n", + (int) cabi, + (unsigned long) cabi->cpu_period_used_ticks, + (unsigned long) cabi->cpu_period_available_ticks); + + if (cabi->cabi_id == OVERLOAD_CABI_ID) { + cabi->overload |= CABI_IS_OVERLOAD; + + cabi_debug("cabi state overload(0x%x), signal sent.\n", + (int) cabi->overload); + + cabi_send_signal(cabi, CABI_SIGPID(cabi), + CABI_SIGNUM(cabi)); + } + } else { + if (cabi->cabi_id == OVERLOAD_CABI_ID) { + + cabi_debug("overload(0x%x), no signal sent.\n", + (int) cabi->overload); + + cabi->overload = CABI_IS_NULL; + } + } + return CABI_SUCCESS; +} + diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_procfs.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_procfs.c --- ./linux-2.6.18.1/drivers/cabi/cabi_procfs.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_procfs.c 2007-04-04 09:57:21.000000000 +0900 @@ -0,0 +1,209 @@ + /* + * linux/drivers/cabi/cabi_procfs.c - implements the interfaces for procfs. + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to doly@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +#include +#include +#include + +#include + +#define MAX_LEN 10 +#define NR_CABI 1000 +#define ENTRIES 4 + + +#ifdef CONFIG_PROC_FS + +/* proc root directory */ +static struct proc_dir_entry *proc_cabi_dir; +/* proc object_id directories */ +static struct proc_dir_entry *cabi_id_dir [NR_CABI]; + +static int +proc_cabi_status_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_proc(cabi, page); +} + +static int +proc_cabi_base_status_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + char *p = page; + extern int cabi_account_base_status_proc(char *); + + p += cabi_account_base_status_proc(p); + + return (p - page); +} + +static int +proc_cabi_block_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_block_proc(cabi, page); +} + +static int +proc_cabi_bindpid_read(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_bindpid_proc (cabi, page); +} + +static int +proc_cabi_time_read (char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + cabi_account_t cabi = (cabi_account_t) data; + return cabi_account_read_time_proc(cabi, page); +} + +void __init +cabi_proc_init(void) +{ + struct proc_dir_entry *proc_cabi_status; + + /* proc directory entry */ + proc_cabi_dir = create_proc_entry("cabi", S_IFDIR, 0); + + if (!proc_cabi_dir) { + printk("Cannot create /proc/cabi\n"); + } + + proc_cabi_status = create_proc_entry("cabi_status", S_IFREG | S_IRUGO, + proc_cabi_dir); + proc_cabi_status->read_proc = proc_cabi_base_status_read; +} + + +struct cabi_entry_list { + const char *name; + int (*f)(char *, char **, off_t, int, int *, void *); +} CABI_PROC_ENTRY[] = { + { "status", proc_cabi_status_read}, + { "term_act", proc_cabi_block_read}, + { "bind_pid", proc_cabi_bindpid_read}, + { "time_set", proc_cabi_time_read}, +}; + +void +cabi_register_proc_account(cabi_account_t cabi) +{ + int i; + struct proc_dir_entry *entry; + unsigned char string[MAX_LEN]; + + sprintf(string, "%d", (int) cabi->cabi_id); + cabi_id_dir[cabi->cabi_id] = proc_mkdir (string, proc_cabi_dir); + + if (!cabi_id_dir[cabi->cabi_id]) + printk("Cannot create /proc/cabi/%d\n", (int)cabi->cabi_id); + + + for (i = 0; i < ENTRIES; i++) { + entry = create_proc_entry (CABI_PROC_ENTRY[i].name, + S_IFREG|S_IRUGO, cabi_id_dir[cabi->cabi_id]); + + if (!entry) + printk("Cannot create /proc/cabi/%d/%s\n", + (int) cabi->cabi_id, CABI_PROC_ENTRY[i].name); + + entry->nlink = 1; + entry->data = cabi; + entry->read_proc = *CABI_PROC_ENTRY[i].f; + } +} + + +void +cabi_proc_account_create(cabi_account_t cabi) +{ + + cabi_debug ("cabi_proc_account_create: cabi(0x%x) cabi_id (%d) \n", + (int) cabi, (int) cabi->cabi_id); + cabi_register_proc_account(cabi); + + +} + +void +cabi_proc_account_destroy(cabi_account_t cabi) +{ + char buf[16]; + + cabi_debug ("cabi_proc_account_destroy: cabi(%d)", + (int) cabi->cabi_id); + sprintf(buf, "%d", (int) cabi->cabi_id); + remove_proc_entry(buf, proc_cabi_dir); +} + +#endif /* CONFIG_PROC_FS */ diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_sched.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_sched.c --- ./linux-2.6.18.1/drivers/cabi/cabi_sched.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_sched.c 2007-05-19 12:34:00.000000000 +0900 @@ -0,0 +1,158 @@ + /* + * linux/drivers/cabi/cabi_sched.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * Authors: Midori Sugaya, Hirotaka Ishikawa + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANYARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include + + /**/ +/* #undef DEBUG_CABI_SCHED */ + /**/ +extern cabi_account_t cabi_current_account; + +void (*cabi_schedule_hook) (struct task_struct *, struct task_struct *); + +void +cabi_schedule_cpu(struct task_struct *prev, struct task_struct *next) +{ + cpu_tick_data_t now; + cabi_account_t prev_cabi = TASK_ACCOUNT(prev); + cabi_account_t next_cabi = TASK_ACCOUNT(next); + + + if (prev_cabi || next_cabi) { + cabi_debug + ("pid(%d) cabi(0x%x)" + " -> pid(%d) cabi(0x%x) \n", + prev->pid, (int) prev_cabi, + next->pid, (int) next_cabi); + } + + /* + * In this point, if the process is belong to the different + * accounting object (cabi), the enforce timer should be + * stopped at this time. + */ + + if (prev_cabi != next_cabi) { + //cabi_enforce_timer_cancel(); + /* if there is a current cabi, stop it */ + + /* debug */ + cabi_debug_entities(cabi_current_account, prev_cabi); + + /* + * if the previous scheduled process is belong to the + * prev_cabi, accounting object (cabi) should be checked + * whether it is deplated or not through the function + * cabi_stop_account (cabi_account_check_enforce) + */ + if (prev_cabi == cabi_current_account) { + + /* debug */ + cabi_debug_entities (cabi_current_account, + prev_cabi); + + if (cabi_current_account) { + + /* get time and stop accounting */ + cabi_rdticks(&now); + cabi_stop_account(cabi_current_account, &now); + } + } + + /* if there is a cabi for next, start it */ + if ((cabi_current_account = next_cabi)) { + + + /* debug */ + cabi_debug_entities (cabi_current_account, + next_cabi); + /* start accounting */ + cabi_start_account(next_cabi); + } + } + //cabi_current_account = next_cabi; +} + +void +cabi_enable_schedule_cpu(void) +{ + if (!cabi_schedule_hook) { + cabi_schedule_hook = cabi_schedule_cpu; + cabi_debug + ("cabi_enable_schedule_cpu: cabi_schedule_hook enabled\n"); + } +} + +void +cabi_disable_schedule_cpu(void) +{ + if (cabi_schedule_hook) { + cabi_schedule_hook = (void *) 0; + + cabi_debug + ("cabi_disable_schedule_cpu:cabi_schedule_hook disabled\n"); + } +} diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_signal.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_signal.c --- ./linux-2.6.18.1/drivers/cabi/cabi_signal.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_signal.c 2007-04-04 12:10:15.000000000 +0900 @@ -0,0 +1,118 @@ + /* + * linux/drivers/cabi/cabi_signal.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * + * Authors: Midori Sugaya, Hirotaka Ishikawa + * + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include + +int +cabi_send_signal(cabi_account_t cabi, int pid, int sig) +{ + + int error; + struct siginfo info; + struct task_struct *tsk; + + /* Set the siginfo */ + info.si_signo = sig; + info.si_errno = 0; + info.si_code = SI_KERNEL; + info.si_pid = 0; + info.si_uid = 0; + + if (sig <= 0) + return -EINVAL; + + /* This is only valid for normal process(not idle process). */ + if (pid <= 0) + return -EINVAL; + + /* search process by pid */ + if (!(tsk = __cabi_find_process_by_pid(pid))) { + + /* debug */ + cabi_debug_signal_pid (pid); + + /* return */ + error = -ESRCH; + return error; + } else { + + /* debug */ + cabi_debug_signal_attrs (pid, sig, tsk); + + /* send signal */ + error = send_sig_info(sig, &info, tsk); + + if (error > 0) { + cabi->signal_block = SIGNAL_ON; + cabi->signal_count++; + } + + } + return error; +} diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_syscalls.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_syscalls.c --- ./linux-2.6.18.1/drivers/cabi/cabi_syscalls.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_syscalls.c 2007-06-17 00:06:37.000000000 +0900 @@ -0,0 +1,595 @@ +/* + * linux/drivers/cabi/cabi_account.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * 2007 Modified by Midori SUGAYA to change interfaces. + * 2005-2. New release based on LinuxRK. by Midori SUGAYA, Hirotaka + * ISHIKAWA. + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * This file is derived from software distributed under the following terms: + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * - struct regist - is for manipulating the group of + * processes. Especially used in the binding procedure + * of the group of processes. + */ +struct rglist { + int count; + pid_t pid; + struct task_struct *tsk; + struct list_head rg_link; +}; +typedef struct rglist *rglist_t; +struct list_head rglist_head; + +/* + * Linux proc file system interface + */ +#include +#include + +extern int cabi_sanity_check_euid(struct task_struct *tsk); + +/* + * Name: sys_cabi_account_create + * + * Create a accounting object named cabi. Mainly sanitary checks + * of the parameters. + * + */ +asmlinkage int +sys_cabi_account_create(struct cabi_uaccount *ucabi) +{ + + struct cabi_uaccount user_cabi; + cabi_account_t cabi; + unsigned long ret; + + /* permission check */ + if (current->euid) { + cabi_sanity_check_euid (current); + goto error_return; + } + + CABI_DBG; + /* parameter copy */ + if (copy_from_user(&user_cabi, ucabi, + sizeof (struct cabi_uaccount))) + return CABI_EINVAL; + + + /* parameter check */ + if ((ret = cabi_sanity_check_ucabi (&user_cabi)) > 0) { + goto error_return; + } + + /* cpu_time and cpu_period should be checked. */ + if ((ret = cabi_sanity_check_timespec_c_and_t + (&user_cabi.cpu_time, + &user_cabi.cpu_period)) > 0) { + goto error_return; + } + + /* check policy integrity */ + cabi_sanity_check_operation (&user_cabi); + + /* + * for overload cabi, check parameters and set a new cpu_time. + */ + if (user_cabi.pm.bind_proc_type == BIND_IDLE_PROC) { + cabi_sanity_check_overload_id (); + cabi_sanity_check_sigoperation (&user_cabi); + + } + + /* parameter check */ + cabi_sanity_check_parameter_to_copy + (&user_cabi.cpu_time, + &user_cabi.cpu_period, + &user_cabi.pm); + + /* call create API */ + if (!(cabi = cabi_account_create(&user_cabi.cpu_time, + &user_cabi.cpu_period, + &user_cabi.pm))) + goto error_return; + + /* copy the result vaule to return the caller */ + ret = copy_to_user(&ucabi->cabi_id, &cabi->cabi_id, + sizeof (cabi_object_t)); + + if (ret < 0) + goto error_return; + + return CABI_SUCCESS; + +error_return: + free (&user_cabi); + free (&ucabi); + EXIT; + + return CABI_CREATE_ERR; + +} + + +/* + * Name: sys_cabi_account_set + * + * Set the parameters to a specified accounting object (cabi). + */ +asmlinkage int +sys_cabi_account_set(unsigned long cabi_id, struct cabi_uaccount *ucabi) +{ + struct cabi_uaccount user_cabi; + cabi_account_t cabi; + int ret; + + /* permission check */ + if (current->euid) { + cabi_sanity_check_euid (current); + return CABI_EACCESS; + } + + /* null pointer check */ + if (!ucabi) + return CABI_EINVAL; + + /* parameter copy */ + if (copy_from_user(&user_cabi, ucabi, + sizeof (struct cabi_uaccount))) + return CABI_EINVAL; + + /* parameter check */ + if ((ret = cabi_sanity_check_ucabi (&user_cabi)) > 0) { + goto error_return; + } + + /* cpu_time and cpu_period should be checked. */ + if ((ret = cabi_sanity_check_timespec_c_and_t + (&user_cabi.cpu_time, + &user_cabi.cpu_period)) > 0) { + goto error_return; + } + + if ((cabi = search_cabi(cabi_id)) == NULL) { + return CABI_ENOEXIST; + } else { + if (user_cabi.pm.bind_proc_type != + cabi->pm.bind_proc_type) + return CABI_EINVAL; + } + + /* + * for overload cabi, check parameters and set a new cpu_time. + */ + if (user_cabi.pm.bind_proc_type == BIND_IDLE_PROC) { + if ((cabi = search_cabi(OVERLOAD_CABI_ID)) == NULL) { + return CABI_EINVAL; + } + if (user_cabi.pm.operation != OP_SIGNAL) { + return CABI_EINVAL; + } + } + + /* pass the new parameter to cabi */ + ret = cabi_account_set(cabi_id, + &user_cabi.cpu_time, + &user_cabi.cpu_period, + &user_cabi.pm); + + if (ret < 0) { + return CABI_ERROR; + } else + return CABI_SUCCESS; +error_return: + free (&ucabi); + free (&user_cabi); + EXIT; + + return CABI_ERROR; +} + + +/* + * Name: sys_cabi_account_get + * + * Get the parameters from a specified accounting object (cabi). + */ + +asmlinkage int +sys_cabi_account_get(unsigned long cabi_id, struct cabi_uaccount *ucabi) +{ + struct list_head *proc_list; + struct rs_proc_list *rs_proc = NULL; + unsigned long ret; + cabi_account_t cabi = NULL_ACCOUNT; + cpu_capacity_quad_t rev_qc; + + /* null pointer check */ + if (!ucabi) + return CABI_EINVAL; + + /* find cabi address */ + if (!(cabi = search_cabi(cabi_id))) + return CABI_ENOEXIST; + + proc_list = cabi->cpu_proc_list.next; + while (proc_list != &cabi->cpu_proc_list) { + /* get a rs_proc */ + rs_proc = + list_entry(proc_list, + struct rs_proc_list, rs_proc_list); + + /* next element */ + proc_list = proc_list->next; + } + + /* if this is overload cabi, re-calculate parameters. */ + if (cabi->pm.bind_proc_type == BIND_IDLE_PROC){ + capacity_overload(&cabi->cpu_time, + &cabi->cpu_period, &rev_qc); + ret = copy_to_user(&ucabi->cpu_time, &rev_qc, + sizeof (ucabi->cpu_time)); + } else { + ret = copy_to_user(&ucabi->cpu_time, &cabi->cpu_time, + sizeof(ucabi->cpu_time)); + } + + ret = copy_to_user(&ucabi->cpu_period, &cabi->cpu_period, + sizeof (ucabi->cpu_period)); + ret = copy_to_user(&ucabi->pm, &cabi->pm, + sizeof (ucabi->pm)); + ret = copy_to_user(&ucabi->cabi_id, &cabi->cabi_id, + sizeof (ucabi->cabi_id)); + + if (ret < 0) + return CABI_ERROR; + return CABI_SUCCESS; +} + + +/* + * Name: sys_cabi_account_destory + * + * Destory a accounting object. + * + */ +asmlinkage int +sys_cabi_account_destroy(unsigned long cabi_id) +{ + int ret; + + /* permission check */ + if (current->euid) { + cabi_sanity_check_euid (current); + return CABI_EACCESS; + } + + + if (cabi_id <= 0) + return CABI_EINVAL; /* invalid argument */ + + ret = cabi_account_destroy(cabi_id); + + return ret; +} + + +/* + * Name: sys_cabi_account_bind_pid + * + * Bind a process to a accounting object. + * + */ +asmlinkage int +sys_cabi_account_bind_pid(unsigned long cabi_id, pid_t pid) +{ + + int ret; + struct task_struct *tsk; + + /* permission check */ + if (current->euid) { + cabi_sanity_check_euid (current); + return CABI_EACCESS; + } + + /* parameter check */ + if (pid_check(pid)) { + return CABI_EINVAL; /* invalid argument */ + } + + /* find overload cabi address. */ + if (cabi_id == OVERLOAD_CABI_ID) { + if (pid != IDLE_PROCESS) { + bind_pid_error(pid); + return CABI_EINVAL; + } + if (!(tsk = __cabi_find_idle_process(pid))) { + bind_pid_error(pid); + return CABI_EPNOEXIST; /* PID(0) dose not exist. */ + } + /* idle process attached. */ + } else { + if (!(tsk = __cabi_find_process_by_pid(pid))) { + bind_pid_error(pid); + return CABI_EPNOEXIST; /* PID dose not exist. */ + } + } + + /* if the task has been registered, rerun. */ + if (TASK_ACCOUNT(tsk)) { + cabi_account_attached (); + if (cabi_id == TASK_ACCOUNT(tsk)->cabi_id) { + /* PID is already registered into AO. */ + return CABI_EREGIST; + } else { + /* PID is registered into another AO. */ + return CABI_ENOAVLE; + } + } + + /* call a function to attach */ + ret = cabi_account_attach(cabi_id, tsk); + + return ret; + +} + + +/* + * Name: sys_cabi_account_bind_pgid + * + * Bind a grounp of processes to a accounting object. + * + */ +asmlinkage int +sys_cabi_account_bind_pgid(unsigned long cabi_id, pid_t pgid) +{ + + cabi_account_t cabi; + struct rglist *rg, *tmp; + struct list_head *reg_list; + struct task_struct *tsk; + int i, ret; + int already_registered, shouldbe_registered, + group_member, rglist_count; + + + /* permission check */ + if (current->euid) { + cabi_sanity_check_euid (current); + return CABI_EACCESS; + } + + /* if pgid is 0 or < 0, error return */ + if (pgid_check (pgid)) { + return CABI_EINVAL; + } + + already_registered = shouldbe_registered = + group_member = rglist_count = 0; + + INIT_LIST_HEAD(&rglist_head); + + /* check cabi_id */ + if (cabi_id_check(cabi_id)) { + return CABI_EINVAL; /* invalid argument */ + } + + /* current(caller) check */ + if (TASK_ACCOUNT(current)) { + cabi = TASK_ACCOUNT(current); + if (cabi->cabi_id == cabi_id) { + already_registered++; + } else { + /* If the caller was already binded to other AO, we + * return error. */ + return CABI_ENOAVLE; + } + } else { + /* + * If the caller process has not bind any AO, we shoud + * bind it to the requested AO. But we will not do + * anything here, because for_each_task() routine picks + * up a process as a member of the target group process. + */ + } + + /* + * If the process which is belong to the same group should be + * bind the requested AO. + */ + read_lock(&tasklist_lock); + for_each_process(tsk) { + if (process_group(tsk) == pgid) { + group_member++; + printk("bind_pgid: tsk->pgid %d group_member %d\n", + process_group(tsk), group_member); + /* + * The process which has the right pgid was found. + * Next, we shoud check if this process has been + * already bind to other cabi, if so, error return. + */ + if (TASK_ACCOUNT(tsk)) { + printk("bind_pgid: this account already " + "attached to this process. " + " pid(%d) cabi(0x%x)\n", + tsk->pid, (int) TASK_ACCOUNT(tsk)); + /* + * If the process has been registered + * the requested cabi, count up, else + * error return. + */ + cabi = TASK_ACCOUNT(tsk); + if (cabi->cabi_id == cabi_id) { + already_registered++; + } else { + read_unlock(&tasklist_lock); + return CABI_ENOAVLE; + } + } else { + /* If the task has not been registered, + * we should bind it. But here, we only + * registerd the list. + */ + if((rg = malloc(sizeof + (struct rglist))) == NULL) { + read_unlock(&tasklist_lock); + return CABI_ENOMEM; + } + bzero(rg, sizeof (struct rglist)); + INIT_LIST_HEAD(&rg->rg_link); + + rg->pid = tsk->pid; + rg->tsk = tsk; + + list_add(&rg->rg_link, &rglist_head); + rglist_count++; + shouldbe_registered++; + } + } + } + read_unlock(&tasklist_lock); + + if (group_member == 0) { + return CABI_EPGNOEXIST; + } else if (group_member == already_registered) { + return CABI_EREGIST; + } else { + /* regist processes */ + reg_list = &rglist_head; + for (i = 0; i < shouldbe_registered + 1; i++) { + if (reg_list == &rglist_head) { + reg_list = reg_list->next; + } else { + tmp = list_entry(reg_list, + struct rglist, rg_link); + if ((ret = + cabi_account_attach(cabi_id, + tmp->tsk))!= CABI_SUCCESS) { + return ret; + } + reg_list = reg_list->next; + } + } + } + + TEXIT; + + return CABI_SUCCESS; +} + + +/* + * Name: sys_cabi_account_unbind + * + * Unbind a process which has been attached to a specified + * accounting object. + * + */ +asmlinkage int +sys_cabi_account_unbind(pid_t pid) +{ + + struct task_struct *tsk; + int ret; + + /* permission check */ + if (current->euid) { + cabi_sanity_check_euid (current); + return CABI_EACCESS; + } + + /* pid check */ + if (pid_check(pid)) { + return CABI_EINVAL; /* Invalid argument */ + } + + /* find overload cabi address. */ + if (pid == IDLE_PROCESS) { + if (!(tsk = __cabi_find_idle_process(pid))) { + printk("account_unbind: idle (%d) failed.\n", pid); + return CABI_EPNOEXIST; /* PID(0) dose not exist. */ + } + } else { + if (!(tsk = __cabi_find_process_by_pid(pid))) { + printk("account_unbind: invalid pid(%d)\n", pid); + return CABI_EPNOEXIST; /* PID dose not exist. */ + } + } + + if (!TASK_ACCOUNT(tsk)) { + printk("account_unbind: no account attached to " + "this process. pid(%d)\n", tsk->pid); + return CABI_ENOBIND; + } + + ret = cabi_account_detach(tsk); + return ret; +} + +asmlinkage int +sys_cabi_account_eval (int eventtype) +{ + + int flag; + + switch (eventtype) { + case 0: + cabi_dump_init(); + break; + case 1: /* this is the first time */ + flag = 1; + cabi_dump_read(flag); + break; + case 2: + flag = 0; + cabi_dump_read(flag); + break; + case 3: + cabi_dump_end(); + break; + default: + break; + + } + return 0; +} + diff -urN ./linux-2.6.18.1/drivers/cabi/cabi_timer.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_timer.c --- ./linux-2.6.18.1/drivers/cabi/cabi_timer.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/cabi_timer.c 2007-06-17 00:07:43.000000000 +0900 @@ -0,0 +1,263 @@ + /* + * linux/drivers/cabi/cabi_timer.c + * + * CABI -- CPU Accounting and Blocking Interfaces. + * + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * + * This software was developed by the Waseda University and Montavista Software, + * Inc. Funding for this project was provided by IPA (Information-technology + * Promotion Agency, Japan). This software may be used and distributed + * according to the terms of the GNU Public License, incorporated herein by + * reference. + * + * This project was developed under the direction of Dr. Tatsuo Nakajima. + * Authors: Midori Sugaya, Hirotaka Ishikawa + * Please send bug-reports/suggestions/comments to qos@dcl.info.waseda.ac.jp + * + * Futher details about this project can be obtained at + * http://dcl.info.waseda.ac.jp/osrg/ + * + * This is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This file is derived from software distributed under the following terms: + */ + /* + * Real-time and Multimedia Systems Laboratory + * Copyright (c) 1999 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Real-Time and Multimedia Systems Laboratory + * Attn: Prof. Raj Rajkumar + * Electrical and Computer Engineering, and Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * or via email to raj@ece.cmu.edu + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include +#include +#include +#include +#include +#include +#include + +__inline__ void +cabi_tstojiffie(struct timespec *tp, unsigned long *jiff) +{ + *jiff = HZ * tp->tv_sec; + *jiff += (tp->tv_nsec + (NANOSEC / HZ)) / (NANOSEC / HZ); +} +extern cabi_account_t cabi_current_account; + +/* + * cabi_replenish_timer_process(cabi_timer_t tmr) + */ +void +cabi_replenish_timer_process(struct hrtimer *tmr) +{ + + int ret; + cabi_account_t cabi; + ENTER; + + cabi = (cabi_account_t) tmr->data; + cabi_account_replenish(cabi); + + /* debug parameters */ + cabi_debug_info (cabi); + + /*check resolution */ + check_hrtimer_res(); + + /* set new parameters */ + tmr->expires.tv64 = (cabi->cpu_period.tv_sec * NANOSEC) + + cabi->cpu_period.tv_nsec; + + /* check expire prameter */ + check_rep_expires (tmr->expires); + + /* if there are bit in signal_block, off it */ + if (cabi->pm.operation == OP_SIGNAL && cabi->signal_block) + cabi->signal_block = SIGNAL_OFF; + + /* Enqueue the timer */ + hrtimer_start (tmr, tmr->expires, HRTIMER_REL); + + EXIT; +} + +/* + * cabi_replenish_timer_create(): + * Create a timer to replenish a account, add it to the queue. + * Set a linux timer if necessary. + */ +#define INIT_TIMEOUT 10000000 +void +cabi_replenish_timer_init(cabi_account_t cabi, cpu_tick_t ticks) +{ + + struct hrtimer *tmr = &cabi->cpu_replenish_hrtmr; + struct timespec res; + + ENTER; + + hrtimer_init (tmr, CLOCK_REALTIME, HRTIMER_REL); + + /* check resolution */ + check_hrtimer_res (); + + /* set parameter to timer */ + tmr->expires.tv64 = INIT_TIMEOUT; + tmr->function = cabi_replenish_timer_process; + tmr->data = (char *) cabi; + + /* debug */ + cabi_debug_info (cabi); + + /* Enqueue the timer */ + hrtimer_start(tmr, tmr->expires, HRTIMER_REL); + EXIT; +} + +void +cabi_replenish_timer_cancel(cabi_account_t cabi) +{ + struct hrtimer *tmr = &cabi->cpu_replenish_hrtmr; + hrtimer_cancel(tmr); + +} + +/* + * Enforcement timer management + */ + +extern enum hrtimer_restart cabi_enforce_timer_process(struct hrtimer *tmr); +static struct hrtimer cabi_enforce_hrtmr; + +void +cabi_enforce_timer_start(cabi_account_t cabi, cpu_tick_t next_available_ticks) +{ + + struct hrtimer *tmr = &cabi_enforce_hrtmr; + struct timespec ts; + int ret; + unsigned long flags; + + ENTER; + + /* convert tick to timespec */ + tick2ts(next_available_ticks, &ts); + + cabi_spin_lock (flags); + /* set timer parameter */ + tmr->expires.tv64 = (ts.tv_sec * NANOSEC) + ts.tv_nsec; + tmr->data = (char *) cabi; + + check_enf_expires (tmr->expires); + + if (tmr->expires.tv64 <= 0) { + if (cabi->cpu_state != CABI_IS_DEPLETED) + cabi->cpu_state &= CABI_IS_DEPLETED; + /* check*/ + check_exstate (tmr->expires, cabi); + + } + + /* set hrtimer */ + ret = hrtimer_start (tmr, tmr->expires, HRTIMER_REL); + cabi_spin_unlock (flags); + + EXIT; +} + +/* + * Cancel enforce_timer and set timer to next jiffy + */ +void +cabi_enforce_timer_cancel(void) +{ + struct hrtimer *tmr = &cabi_enforce_hrtmr; + int ret = -1; + ENTER; + + ret = hrtimer_try_to_cancel(&cabi_enforce_hrtmr); + check_cancel (ret); + /* + * the time state should be HRTIMER_STATE_INACTIVE 0x0 + */ + EXIT; +} + +/* + * Process enforce timer expiration. + */ +enum hrtimer_restart +cabi_enforce_timer_process(struct hrtimer *tmr) +{ + + cabi_account_t cabi; + + cabi = (cabi_account_t) tmr->data; + + /* make sure if cabi corresponds to the current cabi */ + if (cabi_current_account == cabi) { + + /* debug */ + cabi_debug_entities (cabi_current_account, cabi); + + /* enforce the account */ + cabi_account_enforce(cabi_current_account); + } + return HRTIMER_NORESTART; +} + +void +cabi_timer_start(void) +{ + ENTER; + hrtimer_init (&cabi_enforce_hrtmr, CLOCK_REALTIME, HRTIMER_REL); + cabi_enforce_hrtmr.function = cabi_enforce_timer_process; + EXIT; +} + +int +cabi_account_read_time_proc(cabi_account_t cabi, char *buf) +{ + char *p = buf; + + p += sprintf(p, "timespec \n"); + + return (p - buf); +} + バイナリー・ファイル./linux-2.6.18.1/drivers/cabi/examples/.cb_fifo_crebid.c.swoとlinux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/.cb_fifo_crebid.c.swoは違います バイナリー・ファイル./linux-2.6.18.1/drivers/cabi/examples/.cb_fifo_crebid.c.swpとlinux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/.cb_fifo_crebid.c.swpは違います バイナリー・ファイル./linux-2.6.18.1/drivers/cabi/examples/.nfs003b922700000001とlinux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/.nfs003b922700000001は違います diff -urN ./linux-2.6.18.1/drivers/cabi/examples/Makefile linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/Makefile --- ./linux-2.6.18.1/drivers/cabi/examples/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/Makefile 2007-05-06 15:36:08.000000000 +0900 @@ -0,0 +1,69 @@ +CABIDIR = ../.. +CC = $(CROSS_COMPILE)gcc -g +CFLAGS = -O2 -Wall +LIBS = -L../lib -lcabi +INCLUDES = -I../../../include -I/usr/include + +OBJS = cabi_create cabi_destroy cabi_bind cabi_unbind cabi_set cabi_get \ + cabi_overload_create cabi_overload_destroy \ + cabi_create_bind cabi_exec_bind cabi_fifo_crebid \ + cabi_defsrv_crebid cabi_ts_crebid cabi_fifo_crebid_soft \ + cabi_fifo_crebid_hard cabi_ctimer cabi_create_loop\ + +all: cabi_create cabi_destroy cabi_bind cabi_unbind cabi_set cabi_get cabi_overload_create cabi_overload_destroy cabi_create_bind cabi_exec_bind cabi_fifo_crebid cabi_defsrv_crebid cabi_ts_crebid cabi_fifo_crebid_soft cabi_fifo_crebid_hard cabi_ctimer cabi_create_loop \ + +cabi_create: cb_create.c + $(CC) -o cabi_create cb_create.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_destroy: cb_destroy.c + $(CC) -o cabi_destroy cb_destroy.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_bind: cb_bind.c + $(CC) -o cabi_bind cb_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_unbind: cb_unbind.c + $(CC) -o cabi_unbind cb_unbind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_set: cb_set.c + $(CC) -o cabi_set cb_set.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_get: cb_get.c + $(CC) -o cabi_get cb_get.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_overload_create: cb_overload_create.c + $(CC) -o cabi_overload_create cb_overload_create.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_overload_destroy: cb_overload_destroy.c + $(CC) -o cabi_overload_destroy cb_overload_destroy.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_create_bind: cb_create_bind.c + $(CC) -o cabi_create_bind cb_create_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_exec_bind: cb_exec_bind.c + $(CC) -o cabi_exec_bind cb_exec_bind.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_fifo_crebid_soft: cb_fifo_crebid_soft.c + $(CC) -o cabi_fifo_crebid_soft cb_fifo_crebid_soft.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_fifo_crebid_hard: cb_fifo_crebid_hard.c + $(CC) -o cabi_fifo_crebid_hard cb_fifo_crebid_hard.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_fifo_crebid: cb_fifo_crebid.c + $(CC) -o cabi_fifo_crebid cb_fifo_crebid.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_defsrv_crebid: cb_defsrv_crebid.c + $(CC) -o cabi_defsrv_crebid cb_defsrv_crebid.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_ts_crebid: cb_ts_crebid.c + $(CC) -o cabi_ts_crebid cb_ts_crebid.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_ctimer: cb_timer.c + $(CC) -o cabi_timer cb_timer.c $(CFLAGS) $(INCLUDES) $(LIBS) + +cabi_create_loop: cb_create_loop.c + $(CC) -o cabi_create_loop cb_create_loop.c $(CFLAGS) $(INCLUDES) $(LIBS) + +clean: + rm -rf $(OBJS) *~ + + diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_bind.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_bind.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_bind.c 2006-10-24 16:24:14.000000000 +0900 @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_bind [object_id] [pid]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [pid] : bind process id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + unsigned long cabi_id; + + if (argc != 3) { + usage(); + return 0; + } + + /* set accounting object id */ + cabi_id = atol (argv[1]); + pid = (pid_t) atoi (argv[2]); + + switch (cabi_id) { + case 0: + printf ("object id is 0.\n"); + return 1; + case 1: + printf ("[object_id]=1 is only for overload."); + return 1; + default: + printf ("cabi bind pid\n"); + break; + } + + // Attach this process to the resource set + if ((ret = cabi_account_bind_pid(cabi_id, pid)) != CABI_SUCCESS) { + printf ("cabi_account_bind_pid() faild.(%d)\n", ret); + } else { + printf ("cabi_account_bind_pid: object_id(%d) pid[%d]\n", + (int)cabi_id, pid); + } + + return 0; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_create.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_create.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_create.c 2007-04-16 21:28:16.000000000 +0900 @@ -0,0 +1,119 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ONE_SEC 1000000 + +void usage(void) { + printf ("cabi_create:\n"); + printf (" cabi terminate action [block]:\n"); + printf (" Usage: cabi_create [cpu_time(us)] [cpu_period(us)]\n"); + printf (" cabi terminate action [signal]:\n"); + printf (" Usage: cabi_create [cpu_time(us)] [cpu_period(us)] [pid] [sig] [flag]\n"); + printf ("--------------------------------------------------\n"); + printf (" [cpu_time(us)] : cpu performance time (usec)\n"); + printf (" [cpu_period(us)] : cpu cycle time (usec)\n"); + printf (" [pid] : signal receive pid\n"); + printf (" [sig] : send signal number\n"); + printf (" [flag] : default(current) or else\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + struct cabi_uaccount *ucabi; + long long cpu_time, cpu_period; + int operation, sig, flag; + pid_t pid; + + /* set accounting object id */ + switch (argc) { + case 3: + operation = OP_BLOCK; + cpu_time = atoll (argv[1]); + cpu_period = atoll (argv[2]); + pid = 0; + sig = 0; + flag = 0; + break; + case 6: + operation = OP_SIGNAL; + cpu_time = atoll (argv[1]); + cpu_period = atoll (argv[2]); + pid = atoi (argv[3]); + sig = atoi (argv[4]); + flag = atoi (argv[5]); + break; + default: + usage(); + return 1; + } + printf ("Create CABI object...\n"); + if (cpu_time <= 0) { + printf ("Invalid parameter. cpu_time = %lld nsec\n", cpu_time); + return 1; + } + if (cpu_period <= 0) { + printf ("Invalid parameter. cpu_period = %lld nsec\n", cpu_period); + return 1; + } + if (cpu_time > cpu_period) { + printf ("Invalid parameter. cpu_time > cpu_period\n"); + return 1; + } + + /* create a user cabi */ + if(!(ucabi = (cabi_account_t) malloc (sizeof(struct cabi_uaccount)))) { + printf ("cabi_create: Memory allocation error.\n"); + return 1; + } + + ucabi->pm.policy = PO_CYCLIC; + ucabi->pm.operation = operation; + ucabi->pm.bind_proc_type = BIND_NORMAL_PROC; + + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 0; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 0; + + ucabi->cpu_time.tv_sec = (cpu_time / ONE_SEC); + ucabi->cpu_time.tv_nsec = (cpu_time % ONE_SEC) * 1000; + + ucabi->cpu_period.tv_sec = (cpu_period / ONE_SEC); + ucabi->cpu_period.tv_nsec = (cpu_period % ONE_SEC) * 1000; + + ucabi->pm.cabi_signal.pid = pid; + ucabi->pm.cabi_signal.sig = sig; + ucabi->pm.cabi_signal.flag = flag; + + if ((ret = cabi_account_create (ucabi)) == CABI_SUCCESS) { + printf ("account set create. operation (%d) object_id [%d]\n", + (int)ucabi->pm.operation, + (int)ucabi->cabi_id); + } else { + printf ("cabi_account_create failed.(%d)\n", ret); + } + + if (ucabi->cabi_id == 0) { + printf ("cabi_account_create faild on cpu %x\n", (int)ucabi); + free(ucabi); + return 1; + } + + free(ucabi); + + return 0; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_create_bind.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_create_bind.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_create_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_create_bind.c 2007-04-16 21:33:54.000000000 +0900 @@ -0,0 +1,50 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + struct cabi_uaccount *ucabi; + + pid = getpid(); + ucabi = (cabi_account_t) malloc (sizeof(struct cabi_uaccount)); + + memset (ucabi, 0x00, sizeof(struct cabi_uaccount)); + /* set scheduling and enforce mode */ + ucabi->pm.operation = OP_BLOCK; + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 1000 * 1000 * 20; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 1000 * 1000 * 100; + + if (!(ret = cabi_create_bind (ucabi, pid))) { + printf("account set create. object_id [%d]\n", + (int)ucabi->cabi_id); + } else { + printf("cabi_account_create failed.\n"); + } + + if (ucabi->cabi_id == 0) { + printf("cabi_account_create faild on cpu %x\n", (int)ucabi); + return 1; + } + + free(ucabi); + + return 0; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_defsrv_crebid.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_defsrv_crebid.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_defsrv_crebid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_defsrv_crebid.c 2007-04-17 16:49:22.000000000 +0900 @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +int main ( + int argc, + char *argv[]) +{ + int i, ret; + pid_t pid; + int execution, period; + + //struct sched_param *sched_param; + struct cabi_uaccount *ucabi; + + if (argc < 3) { + printf("Usage:./program [execution] [period]\n"); + return 0; + } + execution = atoi(argv[1]); + period = atoi(argv[2]); + + /* get selef identity */ + pid = getpid(); + ucabi = malloc (sizeof(struct cabi_uaccount)); + + memset(ucabi, 0x00, sizeof(struct cabi_uaccount)); + + //ucabi->pm.term_act = CABI_TERM_BLOCK; + ucabi->pm.policy = PO_DEFSRV; + //ucabi->pm.operation = OP_BOOST; + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 1000 * 1000 * execution; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 1000 * 1000 * period; + + printf("make [DSV] process.\n"); + + /* set accounting object id */ + if (!(ret = cabi_create_bind (ucabi, pid))) { + printf("account set create. object_id [%d]\n", + (int)ucabi->cabi_id); + } else { + printf("cabi_account_create failed.\n"); + } + + if (ucabi->cabi_id == 0) { + printf("cabi_account_create failed on cpu %x\n", (int) ucabi); + return 1; + } + // do some work + for (; ;) + { + for (i = 1; i < 100000000; i++) { + i =+ i; + //printf("count %d\n", i); + } + } + +} + + diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_destroy.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_destroy.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_destroy.c 2006-10-24 16:24:14.000000000 +0900 @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_destroy [object_id]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + unsigned long cabi_id; + + if (argc != 2) { + usage(); + return 0; + } + + /* set the object id */ + cabi_id = atol (argv[1]); + + if ((ret = cabi_account_destroy(cabi_id)) != CABI_SUCCESS) { + printf ("destroy faild.(%d)\n", ret); + } else { + printf ("destroy succeed.\n"); + } + + return 1; + + +} + + diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_exec_bind.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_exec_bind.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_exec_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_exec_bind.c 2006-10-24 16:24:14.000000000 +0900 @@ -0,0 +1,58 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int errno; + +void usage(void) { + printf ("Usage: cabi_exec_bind [object_id] [program...]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [program...] : execute program\n"); +} + +int main (int argc, char *argv[]) +{ + unsigned long cabi_id; + pid_t pid; + int status; + int ret; + + if (argc < 3) { + usage(); + return 0; + } + + cabi_id = atoi (argv[1]); + + if ((pid = fork()) == -1) { + perror("fork()"); + return 1; + } else if (pid > 0) { + if ((ret = cabi_account_bind_pid(cabi_id, pid)) != CABI_SUCCESS) { + printf("exec_bind : cabi_account_bind_pid: faild. (%d)\n", ret); + return 1; + } else { + printf("exec_bind : cabi_account_bind_pid: Account ID(%d)[%d]\n", + (int)cabi_id, pid); + } + waitpid(-1, &status, WNOHANG); + } else { + if (execvp(argv[2], &argv[2]) == -1) { + perror("execv"); + return 1; + } + } + + return 0; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_fifo_crebid.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_fifo_crebid.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_fifo_crebid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_fifo_crebid.c 2007-05-21 09:48:52.000000000 +0900 @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RT_PRIORITY 99 + +int main ( + int argc, + char *argv[]) +{ + int i, j, k, ret; + pid_t pid; + int execution, period; + struct timeval tv1, tv2; + double sec1, sec2, sec; + + struct sched_param *sched_param; + struct cabi_uaccount *ucabi; + + if (argc < 3) { + printf("Usage:./program [execution] [period]\n"); + return 0; + } + execution = atoi(argv[1]); + period = atoi(argv[2]); + + /* get selef identity */ + pid = getpid(); + ucabi = malloc (sizeof(struct cabi_uaccount)); + + memset(ucabi, 0x00, sizeof(struct cabi_uaccount)); + + ucabi->pm.operation = OP_BLOCK; + ucabi->pm.policy = PO_CYCLIC; + ucabi->cpu_time.tv_sec = (execution/1000); + ucabi->cpu_time.tv_nsec = 1000 * 1000 * (execution % 1000); + + ucabi->cpu_period.tv_sec = (period/1000); + ucabi->cpu_period.tv_nsec = 1000 * 1000 * (period % 1000); + + printf("[cpu_time] sec %ld nsec %ld\n", + ucabi->cpu_time.tv_sec, + ucabi->cpu_time.tv_nsec); + printf("[cpu_period] sec %ld nsec %ld\n", + ucabi->cpu_period.tv_sec, + ucabi->cpu_period.tv_nsec); + + /* make this process real-time one */ + sched_param = malloc(sizeof(struct sched_param)); + sched_param->sched_priority = RT_PRIORITY; + sched_setscheduler(pid, SCHED_FIFO, sched_param); + printf("make RT[FIFO] process.\n"); + + /* set accounting object id */ + if (!(ret = cabi_create_bind (ucabi, pid))) { + printf("account set create. object_id [%d]\n", + (int)ucabi->cabi_id); + } else { + printf("cabi_account_create failed.\n"); + } + + if (ucabi->cabi_id == 0) { + printf("cabi_account_create failed on cpu %x\n", (int) ucabi); + return 1; + } + gettimeofday (&tv1, NULL); + for (k = 0; k < 10; k++) { + cabi_account_eval (0); + for (j = 0;j < 100000 ; j++) + { + for (i = 1; i < 100000; i++) { + i =+ i; + //printf("count %d\n", i); + } + } + /* + * Get evaluation result + */ + cabi_account_eval(1); + sleep (2); + for (i = 0; i < 8; i++) { + cabi_account_eval(2); + sleep (2); + } + cabi_account_eval(3); + } + + gettimeofday (&tv2, NULL); + sec1 = tv1.tv_sec + tv1.tv_usec*1000; + sec2 = tv2.tv_sec + tv2.tv_usec*1000; + sec = sec2 - sec1; + printf ("time = %10.3f\n", sec); + + + +} + + diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_get.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_get.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_get.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_get.c 2007-04-16 21:32:49.000000000 +0900 @@ -0,0 +1,79 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_get [object_id]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); +} + +int main (int argc, char *argv[]) +{ + struct cabi_uaccount *ucabi; + unsigned long cabi_id; + unsigned long long cpu_time, cpu_period; + float cpu_ratio; + int ret; + + if (argc != 2) { + usage(); + return 0; + } + + /* set accounting object id */ + cabi_id = atoi (argv[1]); + + if (cabi_id == 0) { + printf("object id is 0\n"); + return 1; + } + + /* create a user cabi */ + ucabi = (struct cabi_uaccount *) malloc (sizeof(struct cabi_uaccount)); + + if ((ret = cabi_account_get (cabi_id, ucabi)) == CABI_SUCCESS) { + printf("object_id (%d)\n", + (int)ucabi->cabi_id); + } else { + if (ret == CABI_ENOEXIST) { + printf("object id(%ld) not found.\n", cabi_id); + } else { + printf("cabi_account_get failed.(%d)\n", ret); + } + return 1; + } + if (!ucabi) { + printf("cabi_account_get faild on cpu %p\n", ucabi); + return 1; + } + + cpu_time = ucabi->cpu_time.tv_sec * 1000 + ucabi->cpu_time.tv_nsec / 1000000; + cpu_period = ucabi->cpu_period.tv_sec * 1000 + ucabi->cpu_period.tv_nsec / 1000000; + cpu_ratio = (float)cpu_time / (float)cpu_period * 100.0; + + printf ("OPERATION (%x)\n", ucabi->pm.operation); + printf ("CPU_TIME (%lu sec %02lu nsec) /CPU_PERIOD (%lu sec %02lu nsec)\n", + ucabi->cpu_time.tv_sec, + ucabi->cpu_time.tv_nsec, + ucabi->cpu_period.tv_sec, + ucabi->cpu_period.tv_nsec); + printf ("CPU_RATIO (%5.2f %%)\n", cpu_ratio); + + free(ucabi); + + return 0; +} + + diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_loop.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_loop.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_loop.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_loop.c 2007-05-06 15:09:02.000000000 +0900 @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define LOOP 10 +#define DELAY_SEC 1 +#define DELAY_USEC 1 + + +int main (int argc, char **argv) +{ + + struct sigaction act, oldact; + struct itimerval value, ovalue; + int i, ret, end; + + /* waiting */ + while (count < LOOP); + + /* release the interrupt */ + setitimer (ITIMER_REAL, &ovalue, &value); + + ret = cabi_account_eval(end); + + /* clear the action */ + sigaction (SIGALRM, &oldact, NULL); + + /* print the result */ + for (i = 0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ONE_SEC 1000000 + +int count = 0; + +void usage(void) { + printf ("Usage: cabi_overload_create [overload_time(us)] [ovlerload_period(us)]\n"); + printf ("--------------------------------------------------\n"); + printf (" [overload_time(us)] : overload cpu performance time (usec)\n"); + printf (" [overload_period(us)] : overload cycle time (usec)\n"); + printf (" [overload_time] / [overload_period] * 100 : overload limit persents.\n"); +} + +void sig(int sig) +{ + printf ("signal %d received. count(%d)\n", sig, count); + count++; +} + + +void loop(void) +{ + int i; + signal(SIGCONT, sig); + for (;; i++) { + /* printf("%02d: prog running...\n", i); */ + sleep (2); + } +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t admin; + long long cpu_time, cpu_period; + + struct cabi_uaccount *ucabi; + cabi_account_t cabi = NULL_ACCOUNT; + int status; + + if (argc != 3) { + usage(); + return 0; + } + cpu_time = atoll (argv[1]); + cpu_period = atoll (argv[2]); + + if (cpu_time <= 0) { + printf ("Invalid parameter. cpu_time = %lld nsec\n", cpu_time); + return 1; + } + if (cpu_period <= 0) { + printf ("Invalid parameter. cpu_period = %lld nsec\n", cpu_period); + return 1; + } + if (cpu_time > cpu_period) { + printf ("Invalid parameter. cpu_time > cpu_period\n"); + return 1; + } + + /* create a resource set */ + ucabi = malloc (sizeof(struct cabi_uaccount)); + + /* make admin process */ + if ((admin = fork()) == -1) { + perror("fork()"); + return 1; + } + else if (admin > IDLE_PROCESS) { + /* this is parent */ + printf ("AO PID = %d\n", getpid()); + printf ("Admin PID = %d\n", admin); + waitpid(-1, &status, WNOHANG); + } else { + printf ("Admin start..pid %d\n", getpid()); + loop(); + } + + printf ("Overload Create!\n"); + + /* set scheduling and enforce mode */ + ucabi->pm.operation = OP_SIGNAL; + ucabi->pm.cabi_signal.pid = admin; + ucabi->pm.cabi_signal.sig = SIGCONT; + + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 0; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 0; + + ucabi->cpu_time.tv_sec = (cpu_time / ONE_SEC); + ucabi->cpu_time.tv_nsec = (cpu_time % ONE_SEC) * 1000; + + ucabi->cpu_period.tv_sec = (cpu_period / ONE_SEC); + ucabi->cpu_period.tv_nsec = (cpu_period % ONE_SEC) * 1000; + + if ((ret = cabi_overload_create (ucabi)) == CABI_SUCCESS) { + printf ("account set create[SIGNAL]. object_id (%d)" + "cabi object address (0x%x) , user cabi address(0x%x)\n", + (int)ucabi->cabi_id, (int)cabi, (int)ucabi); + } else { + kill(admin, SIGKILL); + printf ("Kill admin process (pid = %d)\n", admin); + printf ("cabi_account_create failed.(%d)\n", ret); + return 1; + } + + if (ucabi->cabi_id != OVERLOAD_CABI_ID) { + printf ("cabi_account_create faild on cpu %p\n", cabi); + return 1; + } + + return 0; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_overload_destroy.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_overload_destroy.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_overload_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_overload_destroy.c 2007-03-21 21:45:24.000000000 +0900 @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +extern int cabi_overload_destroy(void); + +int main (void) +{ + int ret; + + if ((ret = cabi_overload_destroy()) == CABI_SUCCESS) { + printf("overload destroy success.\n"); + } else { + printf("overload destroy faild. (%d)\n", ret); + } + return ret; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_set.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_set.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_set.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_set.c 2007-04-16 21:32:05.000000000 +0900 @@ -0,0 +1,145 @@ +/* + * This is sample program for CABI system. + * create accounting object. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ONE_SEC 1000000 + +void usage(void) { + printf ("cabi_set:\n"); + printf (" only cpu ratio change:\n"); + printf (" Usage: cabi_set [object_id] [cpu_time(us)] [cpu_period(us)]\n"); + printf (" cabi terminate action [signel] -> [block]:\n"); + printf (" Usage: cabi_set [object_id] [cpu_time(us)] [cpu_period(us)] [term_act]\n"); + printf (" cabi terminate action [block] -> [signal]:\n"); + printf (" Usage: cabi_set [object_id] [cpu_time(us)] [cpu_period(us)] [term_act] [pid] [sig] [flag]\n"); + printf ("--------------------------------------------------\n"); + printf (" [object_id] : cabi object id\n"); + printf (" [cpu_time(us)] : cpu performance time (usec)\n"); + printf (" [cpu_period(us)] : cpu cycle time (usec)\n"); + printf (" [term_act] : terminate action (block=1, signal=2)\n"); + printf (" [pid] : signal receive process id\n"); + printf (" [sig] : send signal number\n"); + printf (" [flag] : default(current) or else\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + struct cabi_uaccount *ucabi; + unsigned long cabi_id; + long long cpu_time, cpu_period; + int operation, sig, flag; + pid_t pid; + + sig = flag = 0; + pid = 0; + /* set accounting object id */ + switch (argc) { + case 4: + operation = OP_BLOCK; + break; + case 5: + operation = atoi(argv[4]); + if(operation != OP_BLOCK) { + usage(); + return 1; + } + break; + case 8: + operation = atoi(argv[4]); + break; + default: + usage(); + return 1; + } + cabi_id = atoi (argv[1]); + cpu_time = atoll (argv[2]); + cpu_period = atoll (argv[3]); + + switch (operation) { + case OP_BLOCK: + break; + case OP_SIGNAL: + pid = atoi (argv[5]); + sig = atoi (argv[6]); + flag = atoi (argv[7]); + break; + default: + printf ("Invalid parameter.operation = %d\n", operation); + return 1; + } + printf ("Setting...\n"); + if (cabi_id == 0) { + return 1; + } + if (cpu_time <= 0) { + printf ("Invalid parameter. cpu_time = %lld nsec\n", cpu_time); + return 1; + } + if (cpu_period <= 0) { + printf ("Invalid parameter. cpu_period = %lld nsec\n", cpu_period); + return 1; + } + if (cpu_time > cpu_period) { + printf ("Invalid parameter. cpu_time > cpu_period\n"); + return 1; + } + + /* create a user cabi */ + ucabi = (cabi_account_t) malloc (sizeof(struct cabi_uaccount)); + + if ((ret = cabi_account_get (cabi_id, ucabi)) != CABI_SUCCESS) { + printf ("cabi_account_set : cabi_id(%ld) no exist. (%d)\n", cabi_id, ret); + return 1; + } + + /* set time to the timespec */ + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 0; + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 0; + + ucabi->cpu_time.tv_sec = (cpu_time / ONE_SEC); + ucabi->cpu_time.tv_nsec = (cpu_time % ONE_SEC) * 1000; + + ucabi->cpu_period.tv_sec = (cpu_period / ONE_SEC); + ucabi->cpu_period.tv_nsec = (cpu_period % ONE_SEC) * 1000; + + if (argc != 4) { + ucabi->pm.operation = operation; + } + if (operation == OP_SIGNAL) { + ucabi->pm.cabi_signal.pid = pid; + ucabi->pm.cabi_signal.sig = sig; + ucabi->pm.cabi_signal.flag = flag; + } + + if ((ret = cabi_account_set (cabi_id, ucabi)) == CABI_SUCCESS) { + printf ("account set. object_id (%d)", (int)cabi_id); + } else { + printf ("cabi_id = %ld : cabi_account_set failed. (%d)\n", cabi_id, ret); + return 1; + } + + printf ("TERM_ACT (%d)\n", ucabi->pm.operation); + printf ("CPU_TIME (%lu sec %02lu nsec) /CPU_PERIOD (%lu sec %02lu nsec)\n", + ucabi->cpu_time.tv_sec, + ucabi->cpu_time.tv_nsec, + ucabi->cpu_period.tv_sec, + ucabi->cpu_period.tv_nsec); + + free(ucabi); + + return 0; +} diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_timer.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_timer.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_timer.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_timer.c 2007-05-06 12:45:55.000000000 +0900 @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#define LOOP 10 +#define DELAY_SEC 1 +#define DELAY_USEC 1 + + +volatile int count = 0; +struct timeval tv[LOOP]; +struct timezone tz; + + +void sig_action_handler () +{ + + //system("./ctcreate"); + gettimeofday (tv+count, &tz); + count++; +} + +int main () +{ + + struct sigaction act, oldact; + struct itimerval value, ovalue; + int i, ret, end; + end = 1; + + /* set interrupt handler */ + act.sa_handler = sig_action_handler; + act.sa_flags = 0; + sigaction (SIGALRM, &act, &oldact); + + /* set interrupt */ + /* the first interrupt ->it_value */ + /* after the second -> it_interval */ + value.it_value.tv_sec = DELAY_SEC; + value.it_value.tv_usec = DELAY_USEC; + value.it_interval.tv_sec = DELAY_SEC; + value.it_interval.tv_usec = DELAY_USEC; + setitimer (ITIMER_REAL, &value, &ovalue); + + /* waiting */ + while (count < LOOP); + + /* release the interrupt */ + setitimer (ITIMER_REAL, &ovalue, &value); + + ret = cabi_account_eval(end); + + /* clear the action */ + sigaction (SIGALRM, &oldact, NULL); + + /* print the result */ + for (i = 0; i +#include +#include +#include +#include +#include +#include +#include +#include + +#define RT_PRIORITY 50 + +int main ( + int argc, + char *argv[]) +{ + int i, ret; + pid_t pid; + int execution, period; + + struct cabi_uaccount *ucabi; + + if (argc < 3) { + printf("Usage:./program [execution] [period]\n"); + return 0; + } + execution = atoi(argv[1]); + period = atoi(argv[2]); + + /* get selef identity */ + pid = getpid(); + ucabi = malloc (sizeof(struct cabi_uaccount)); + + memset(ucabi, 0x00, sizeof(struct cabi_uaccount)); + + ucabi->pm.operation = OP_BLOCK; + ucabi->pm.policy = PO_CYCLIC; + ucabi->cpu_time.tv_sec = 0; + ucabi->cpu_time.tv_nsec = 1000 * 1000 * execution; + + ucabi->cpu_period.tv_sec = 0; + ucabi->cpu_period.tv_nsec = 1000 * 1000 * period; + + /* make this process real-time one */ + printf("make TS[NORMAL] process.\n"); + + /* set accounting object id */ + if (!(ret = cabi_create_bind (ucabi, pid))) { + printf("account set create. object_id [%d]\n", + (int)ucabi->cabi_id); + } else { + printf("cabi_account_create failed.\n"); + } + + if (ucabi->cabi_id == 0) { + printf("cabi_account_create failed on cpu %x\n", (int) ucabi); + return 1; + } + // do some work + for (; ;) + { + for (i = 1; i < 100000000; i++) { + i =+ i; + //printf("count %d\n", i); + } + } + +} + + diff -urN ./linux-2.6.18.1/drivers/cabi/examples/cb_unbind.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_unbind.c --- ./linux-2.6.18.1/drivers/cabi/examples/cb_unbind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/examples/cb_unbind.c 2006-10-24 16:24:14.000000000 +0900 @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void usage(void) { + printf ("Usage: cabi_unbind [pid]\n"); + printf ("--------------------------------------------------\n"); + printf (" [pid] : unbind process id\n"); +} + +int main (int argc, char *argv[]) +{ + int ret; + pid_t pid; + + if (argc != 2) { + usage(); + return 0; + } + + pid = (pid_t) atoi (argv[1]); + printf ("cabi unbind pid: %d\n", pid); + + // Dettach this process from accounting obiect + if ((ret = cabi_account_unbind(pid)) != CABI_SUCCESS) { + printf ("unbind faild.(%d)\n", ret); + } else { + printf ("unbaind succeed.\n"); + } + + return 0; +} バイナリー・ファイル./linux-2.6.18.1/drivers/cabi/lib/.Makefile.swpとlinux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/.Makefile.swpは違います バイナリー・ファイル./linux-2.6.18.1/drivers/cabi/lib/.cabi_overload_destroy.c.swpとlinux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/.cabi_overload_destroy.c.swpは違います diff -urN ./linux-2.6.18.1/drivers/cabi/lib/Makefile linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/Makefile --- ./linux-2.6.18.1/drivers/cabi/lib/Makefile 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/Makefile 2007-05-06 01:13:28.000000000 +0900 @@ -0,0 +1,29 @@ +INSTALL = /usr/bin/install -c -m 644 +DESTDIR = +KERNELDIR = ../../.. +#KERNELDIR = /usr/src/debug +INCLUDEDIR = /usr +CC = $(CROSS_COMPILE)gcc -g +AR = $(CROSS_COMPILE)ar +RANLIB = $(CROSS_COMPILE)ranlib +SOURCES = $(wildcard *.c) +OBJS = $(SOURCES:.c=.o) +CFLAGS = -DCONFIG_CABI -O3 -Wall -I$(KERNELDIR)/include -I$(INCLUDEDIR)/include + +all: libcabi.so libcabi.a + +libcabi.a: $(OBJS) + $(AR) -r libcabi.a $(OBJS) + $(RANLIB) libcabi.a + +libcabi.so: $(OBJS) + $(CC) -fPIC $(OBJS) -shared -o libcabi.so + +clean: + rm -rf $(OBJS) libcabi.a + +install: libcabi.a + $(INSTALL) libcabi.a $(DESTDIR)/lib/libcabi.a + $(INSTALL) libcabi.so $(DESTDIR)/lib/libcabi.so + $(INSTALL) $(KERNELDIR)/include/cabi/cabi.h $(DESTDIR)/usr/include/cabi/cabi.h + $(INSTALL) $(KERNELDIR)/include/cabi/cabi_error.h $(DESTDIR)/usr/include/cabi/cabi_error.h diff -urN ./linux-2.6.18.1/drivers/cabi/lib/README.cabi linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/README.cabi --- ./linux-2.6.18.1/drivers/cabi/lib/README.cabi 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/README.cabi 2006-10-24 16:24:14.000000000 +0900 @@ -0,0 +1,11 @@ +README file for the cabi library. +=================================== +This file describes the brief instruction abount the cabi library +install. + +Before make, please add the link for kernel for header +directories as follows. + +#ln -sf /usr/src/linux/include/linux /usr/include/linux +#ln -sf /usr/src/linux/asm-i386 /usr/include/asm + diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_bind_pgid.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_bind_pgid.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_bind_pgid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_bind_pgid.c 2007-03-31 19:02:25.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +/* + * int sys_cabi_account_bind_pgid(unsigned long cabi_id, pid_t pgid) + */ + +_syscall2(int, cabi_account_bind_pgid, unsigned long, cabi_id, pid_t, pgid) diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_bind_pid.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_bind_pid.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_bind_pid.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_bind_pid.c 2007-03-31 19:02:56.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +/* + * int sys_cabi_account_bind_pid(unsigned long cabi_id, pid_t pid) + * + */ +_syscall2(int, cabi_account_bind_pid, unsigned long, cabi_id, pid_t, pid) diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_create.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_create.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_create.c 2007-03-31 19:03:23.000000000 +0900 @@ -0,0 +1,19 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * int sys_cabi_account_create(cabi_object_t objectid, cabi_account_t cpu) + */ +_syscall1(int, cabi_account_create, struct cabi_uaccount *, ucabi) + + diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_destroy.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_destroy.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_destroy.c 2007-03-31 19:04:19.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * int sys_cabi_account_destroy (unsigned long cabi_id) + */ +_syscall1(int, cabi_account_destroy, unsigned long, cabi_id) diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_eval.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_eval.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_eval.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_eval.c 2007-05-05 15:16:57.000000000 +0900 @@ -0,0 +1,19 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * int sys_cabi_account_create(cabi_object_t objectid, cabi_account_t cpu) + */ +_syscall1(int, cabi_account_eval, int, eventtype) + + diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_get.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_get.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_get.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_get.c 2007-03-31 19:03:39.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * cabi_uaccount_t sys_cabi_account_get (unsigned long cabi_id, cabi_uaccount_t, ucabi) + */ +_syscall2(int, cabi_account_get, unsigned long, cabi_id, cabi_uaccount_t, ucabi) diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_set.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_set.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_set.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_set.c 2007-03-31 19:04:04.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * int sys_cabi_account_set (unsigned long cabi_id, struct cabi_uaccount_t *cpu) + */ +_syscall2(int, cabi_account_set, unsigned long, cabi_id, struct cabi_uaccount *, ucabi) diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_unbind.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_unbind.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_account_unbind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_account_unbind.c 2007-03-31 19:04:34.000000000 +0900 @@ -0,0 +1,17 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include + +/* + * int sys_cabi_account_unbind (pid_t pid) + */ +_syscall1(int, cabi_account_unbind, pid_t, pid) diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_create_bind.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_create_bind.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_create_bind.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_create_bind.c 2007-04-16 22:43:32.000000000 +0900 @@ -0,0 +1,72 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include +/* + * int cabi_overload_create(cabi_uaccount_t ucabi) + */ + +extern int cabi_account_create (struct cabi_uaccount *); +extern int cabi_account_bind_pid(unsigned long cabi_id, pid_t pid); +extern int cabi_account_destroy(unsigned long cabi_id); + +int +cabi_create_bind (struct cabi_uaccount *ucabi, pid_t pid) +{ + + int retval = -EPERM; + + /* If ucabi has not valid address. */ + if (!ucabi) { + return CABI_EINVAL; + } + + /* call cabi_account_create() */ + if (!(retval = cabi_account_create (ucabi))) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "create_bind: account set create. object_id (%d)" + "user cabi address (0x%x)\n", + (int) ucabi->cabi_id, (int)ucabi); +#endif + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "create_bind failed. (%d)\n", retval); +#endif + goto error; + } + + if (pid < 0) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "create_bind: invalid pid(%d)\n", + (int)pid); +#endif + retval = CABI_EINVAL; /* Invalid argument */ + goto error; + } + + /* call cabi_account_bind_pid */ + if (!(retval = cabi_account_bind_pid(ucabi->cabi_id, pid))) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid: Account ID(%d)[%d]\n", + (int) ucabi->cabi_id, pid); +#endif + return CABI_SUCCESS; + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid() failed.\n"); +#endif + cabi_account_destroy(ucabi->cabi_id); + } + +error: + return retval; +} diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_overload_create.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_overload_create.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_overload_create.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_overload_create.c 2007-04-04 05:43:22.000000000 +0900 @@ -0,0 +1,84 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include + +#define DEBUG_CABILIB 1 + +/* + * int cabi_overload_create(cabi_uaccount_t ucabi) + */ + +extern int cabi_account_create (struct cabi_uaccount *); +extern int cabi_account_bind_pid (unsigned long cabi_id, pid_t pid); + +int +cabi_overload_create (struct cabi_uaccount *ucabi) +{ + + pid_t pid; + int ret; + + /* If ucabi has not valid address. */ + if (!ucabi) { + return CABI_EINVAL; + } + + ucabi->pm.bind_proc_type = BIND_IDLE_PROC; + +#ifdef DEBUG_CABILIB + printf ("pm.bind_proc_type (%x)\n", + ucabi->pm.bind_proc_type); +#endif + + if ((ret = cabi_account_create (ucabi)) == CABI_SUCCESS) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "overload account set create. object_id (%d)" + "user cabi address (0x%x)\n", + (int) ucabi->cabi_id, (int)ucabi); +#endif + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "overload cabi_account_create failed. (%d)\n", + ret); +#endif + return ret; + } + + /* if the system call has been success, then bind the idle process. */ + if (ucabi->cabi_id != OVERLOAD_CABI_ID) { +#ifdef DEBUG_CABILIB + fprintf (stderr, "cabi object_id(%d) did not set. error return.\n", (int) ucabi->cabi_id); +#endif + return CABI_EINVAL; + } + + /* set the idle process */ + pid = IDLE_PROCESS; + + if ((ret = cabi_account_bind_pid(ucabi->cabi_id, pid)) + == CABI_SUCCESS) { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid: Account ID(%d)[%d]\n", + (int) ucabi->cabi_id, pid); +#endif + return CABI_SUCCESS; + } else { +#ifdef DEBUG_CABILIB + fprintf(stderr, "cabi_account_bind_pid() [idle] failed.\n"); +#endif + return ret; + } + free (ucabi); + return CABI_SUCCESS; +} + diff -urN ./linux-2.6.18.1/drivers/cabi/lib/cabi_overload_destroy.c linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_overload_destroy.c --- ./linux-2.6.18.1/drivers/cabi/lib/cabi_overload_destroy.c 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/lib/cabi_overload_destroy.c 2007-03-21 23:08:48.000000000 +0900 @@ -0,0 +1,42 @@ +/* + * Copyright (C) OS Research Group, Waseda University Nakajima Laboratory. + * MontaVista Software, Inc. + * All Rights Reserved. + * any improvements or extensions that they make and grant Waseda University + * the rights to redistribute these changes. + * + */ + +#define __LIBRARY__ +#include +#include +#include + +/* + * int cabi_overload_destroy(void) + */ + +extern int cabi_account_unbind(pid_t pid); +extern int cabi_account_destroy(unsigned long cabi_id); + +int +cabi_overload_destroy(void) +{ + pid_t pid = IDLE_PROCESS; + int ret; + + if ((ret = cabi_account_unbind(pid)) != CABI_SUCCESS) { +#ifdef DEBUG_CABILIB + fprintf (stderr, "cabi_overload_destroy : unbind error. (%d)\n", ret); +#endif + return ret; + } + if ((ret = cabi_account_destroy(OVERLOAD_CABI_ID)) != CABI_SUCCESS) { +#ifdef DEBUG_CABILIB + fprintf (stderr, "cabi_overload_destroy : destroy error. (%d)\n", ret); +#endif + return ret; + } + + return ret; +} diff -urN ./linux-2.6.18.1/drivers/cabi/udivdi3.S linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/udivdi3.S --- ./linux-2.6.18.1/drivers/cabi/udivdi3.S 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/drivers/cabi/udivdi3.S 2007-01-09 23:15:23.000000000 +0900 @@ -0,0 +1,396 @@ + .file "libgcc2.c" + .version "01.01" +gcc2_compiled.: +.section .rodata + .type __clz_tab,@object +__clz_tab: +.byte 0 +.byte 1 +.byte 2 +.byte 2 +.byte 3 +.byte 3 +.byte 3 +.byte 3 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 4 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 5 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 6 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 7 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 +.byte 8 + .size __clz_tab,256 +.text + .align 4 +.globl __udivdi3 + .type __udivdi3,@function +__udivdi3: + subl $28,%esp + pushl %ebp + pushl %edi + pushl %esi + pushl %ebx + movl 56(%esp),%ebx + movl 60(%esp),%edi + movl 48(%esp),%eax + movl %eax,40(%esp) + movl 52(%esp),%edx + movl %edx,16(%esp) + testl %edi,%edi + jne .L25 + cmpl %edx,%ebx + jbe .L26 +#APP + divl %ebx +#NO_APP + movl %eax,%esi + jmp .L30 + .align 4 +.L26: + cmpl $0,56(%esp) + jne .L28 + movl $1,%eax + xorl %edx,%edx + divl %ebx + movl %eax,%ebx +.L28: + movl 16(%esp),%eax + xorl %edx,%edx +#APP + divl %ebx +#NO_APP + movl %eax,%edi + movl %edx,16(%esp) + movl 40(%esp),%eax +#APP + divl %ebx +#NO_APP + movl %eax,%esi + jmp .L30 + .align 4 +.L25: + cmpl %edi,16(%esp) + jae .L31 + xorl %edi,%edi + movl %edi,%esi + jmp .L30 + .align 4 +.L31: +#APP + bsrl %edi,%eax +#NO_APP + movl %eax,%esi + xorl $31,%esi + jne .L38 + cmpl %edi,16(%esp) + ja .L39 + cmpl %ebx,40(%esp) + jb .L45 +.L39: + movl $1,%esi + jmp .L45 + .align 4 +.L38: + movl $32,%ebp + subl %esi,%ebp + movl %esi,%ecx + sall %cl,%edi + movl %edi,20(%esp) + movl %ebx,%eax + movl %ebp,%ecx + shrl %cl,%eax + orl %eax,%edi + movl %esi,%ecx + sall %cl,%ebx + movl 16(%esp),%eax + movl %ebp,%ecx + shrl %cl,%eax + movl %eax,36(%esp) + movl 16(%esp),%eax + movl %esi,%ecx + sall %cl,%eax + movl %eax,20(%esp) + movl 40(%esp),%eax + movl %ebp,%ecx + shrl %cl,%eax + movl 20(%esp),%edx + orl %eax,%edx + movl %edx,16(%esp) + movl %esi,%ecx + sall %cl,40(%esp) + movl %edx,%eax + movl 36(%esp),%edx +#APP + divl %edi +#NO_APP + movl %eax,%esi + movl %edx,16(%esp) +#APP + mull %ebx +#NO_APP + movl %eax,%ebx + movl %edx,%edi + cmpl %edi,16(%esp) + jb .L44 + jne .L45 + cmpl %ebx,40(%esp) + jae .L45 +.L44: + decl %esi +.L45: + xorl %edi,%edi +.L30: + movl %esi,28(%esp) + movl %edi,32(%esp) + movl 28(%esp),%eax + movl 32(%esp),%edx + popl %ebx + popl %esi + popl %edi + popl %ebp + addl $28,%esp + ret +.Lfe1: + .size __udivdi3,.Lfe1-__udivdi3 + .ident "GCC: (GNU) 2.8.1" diff -urN ./linux-2.6.18.1/fs/9p/debug.h linux-2.6.18.1-cabi-20070524-hrt-nrt/fs/9p/debug.h --- ./linux-2.6.18.1/fs/9p/debug.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/fs/9p/debug.h 2007-05-05 01:33:05.000000000 +0900 @@ -71,7 +71,7 @@ } #else /* DEBUG_DUMP_PKT */ static inline void dump_data(const unsigned char *data, unsigned int datalen) -{ + { } #endif /* DEBUG_DUMP_PKT */ diff -urN ./linux-2.6.18.1/include/asm-generic/div64.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-generic/div64.h --- ./linux-2.6.18.1/include/asm-generic/div64.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-generic/div64.h 2007-01-09 23:15:52.000000000 +0900 @@ -55,4 +55,26 @@ #endif /* BITS_PER_LONG */ +/* + * (long)X = ((long long)divs) / (long)div + * (long)rem = ((long long)divs) % (long)div + * + * Warning, this will do an exception if X overflows. + */ +#define div_long_long_rem(a,b,c) div_ll_X_l_rem(a,b,c) + +extern inline long +div_ll_X_l_rem(long long divs, long div, long *rem) +{ + long dum2; + __asm__("divl %2":"=a"(dum2), "=d"(*rem) + : "rm"(div), "A"(divs)); + + return dum2; + +} + + + + #endif /* _ASM_GENERIC_DIV64_H */ バイナリー・ファイル./linux-2.6.18.1/include/asm-i386/.posix_types.h.swpとlinux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-i386/.posix_types.h.swpは違います diff -urN ./linux-2.6.18.1/include/asm-i386/div64.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-i386/div64.h --- ./linux-2.6.18.1/include/asm-i386/div64.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-i386/div64.h 2007-01-09 23:15:52.000000000 +0900 @@ -45,4 +45,5 @@ return dum2; } + #endif diff -urN ./linux-2.6.18.1/include/asm-i386/unistd.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-i386/unistd.h --- ./linux-2.6.18.1/include/asm-i386/unistd.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/asm-i386/unistd.h 2007-05-11 21:04:25.000000000 +0900 @@ -324,6 +324,17 @@ #define __NR_vmsplice 316 #define __NR_move_pages 317 +#ifdef CONFIG_CABI +#define __NR_cabi_account_create 318 +#define __NR_cabi_account_destroy 319 +#define __NR_cabi_account_bind_pid 320 +#define __NR_cabi_account_bind_pgid 321 +#define __NR_cabi_account_unbind 322 +#define __NR_cabi_account_get 323 +#define __NR_cabi_account_set 324 +#define __NR_cabi_account_eval 325 +#endif + #ifdef __KERNEL__ #define NR_syscalls 318 diff -urN ./linux-2.6.18.1/include/cabi/cabi.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/cabi.h --- ./linux-2.6.18.1/include/cabi/cabi.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/cabi.h 2007-05-23 16:05:07.000000000 +0900 @@ -0,0 +1,803 @@ +#ifndef CABI_CABI_H +#define CABI_CABI_H +/* + * Please change the definie to undef if you don't need to + * cabi_debug the debug codes. + */ + +#ifdef CONFIG_X86 +#include +#endif /* #ifdef CONFIG_X86 */ + +#ifdef __KERNEL__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +/* from 2.6.0 64-bit/32-bit devide is allowed by thE + * do_div(). + */ +#else +#include +#include +#include +#include +#endif + +/* + * Types and defines + */ +typedef unsigned long long *cpu_tick_t; +typedef unsigned long long cpu_tick_data_t; + +#define NANOSEC 1000000000L +#define MICROSEC 1000000L +#define MILISEC 1000L +#define MILION 1000000L +#define TENTHOUSANDS 10000L +#define THOUSAND 1000L +#define HUNDRED 100L + + +/* for parameter check */ +#define CABI_TICK_MIN 1 +#define CABI_TIME_SEC_MAX (long)(0x7FFFFFFF / 1000) +#define CHECK_DEGIT(x) ((x)> MICROSEC ? 1 : 0) + +#ifdef CONFIG_X86 +static inline void +cabi_rdtsc(cpu_tick_t data_p) +{ +#if 1 + rdtscll(*data_p); +#else + rdtsc(*(int *) (data_p), *(((int *) data_p) + 1)); +#endif +} +#else +#define CABI_CLOCK 1000000000 +#endif /* #ifdef CONFIG_X86 */ + +/* + * CPU account argument parameter + */ +enum cabi_terminate_operation { + OP_NONE = 0x000, + OP_BLOCK = 0x002, + OP_SIGNAL = 0x004, + OP_DETECT = 0x008, + OP_UNKNOWN = 0x020, + OP_BOOST = 0x040, +}; + +typedef enum cabi_terminate_operation cabi_operation_t; + +enum cabi_bind_proc_type { + BIND_NORMAL_PROC = 0x0, + BIND_IDLE_PROC = 0x1, +}; + +typedef enum cabi_bind_proc_type cabi_bind_type_t; + +enum cabi_account_policy { + PO_NONE = 0x000, + PO_CYCLIC = 0x002, + PO_RM = 0x004, + PO_DEFSRV = 0x008, + PO_VPE = 0x020, + PO_EDF = 0x040, + PO_OVLD = 0x080, +}; +typedef enum cabi_account_policy cabi_account_policy_t; + +enum cabi_replenish_policy { + REP_SOFT = 0x000, + REP_HARD = 0x002, +}; +typedef enum cabi_replenish_policy cabi_replenish_policy_t; + +struct cpu_param { + cabi_account_policy_t policy; /* user can set a policy for each AO */ + cabi_operation_t operation; /* termnate action */ + cabi_replenish_policy_t rep_policy; /* replenish policy */ + cabi_bind_type_t bind_proc_type; /* process bind type */ + struct { + pid_t pid; /* process id */ + int sig; /* signal number */ + int flag; /* default(current) or else */ + } cabi_signal; +}; +typedef struct cpu_param cabi_param_data_t; +typedef struct cpu_param *cabi_param_t; +typedef unsigned long cabi_object_t; + +enum cabi_operation_status { + CABI_BLOCKED = 1, + CABI_UNBLOCK = 0, + CABI_SIGNAL = -1, +}; +typedef enum cabi_operation_status opt_state_t; + +#define CABI_SEND_DEFL 0 +#define CABI_SEND_PID 1 +#define CABI_SIG_DEFL 0 /* or SIGCONT ? */ + +#define CABI_SIGFLAG(cabi) ((cabi)->pm.cabi_signal.flag) +#define CABI_SIGPID(cabi) ((cabi)->pm.cabi_signal.pid) +#define CABI_SIGNUM(cabi) ((cabi)->pm.cabi_signal.sig) + +#define SIGNAL_ON 1 +#define SIGNAL_OFF 0 + +#define LANDOM_BYTES 1 +#define OVERLOAD_CABI_ID 1 +#define FIRST_CABI_ID 2 +#define IDLE_PROCESS 0 +#define CABI_ID_MAX 2147483647 + +/* + * for user applications + */ +struct cabi_uaccount { + struct timespec cpu_time; + struct timespec cpu_period; + struct cpu_param pm; + cabi_object_t cabi_id; +}; +typedef struct cabi_uaccount *cabi_uaccount_t; + +#ifdef __KERNEL__ +/* + * NULL not running + * RUNNING running + * DEPLETED not running and depleted + * RUNNING|DEPLETED running but depleted + */ +enum cabi_account_state { + CABI_IS_NULL = 0x000, /* not running */ + CABI_IS_RUNNING = 0x001, /* actually running */ + CABI_IS_DEPLETED = 0x010, /* it's empty */ + //CABI_IS_BOOST = 0x100, /* boosted priority */ + CABI_IS_OVERLOAD = 0x100, /* overloading */ +}; +typedef enum cabi_account_state cabi_account_state_t; +typedef unsigned long cabi_overload_t; + + +enum cabi_priority_control { + CABI_PRI_NONE = 0x000, + CABI_PRI_BOOST = 0x002, + CABI_PRI_NORMAL = 0x004, + CABI_PRI_RT = 0x008, +}; +typedef enum cabi_priority_control cabi_priority_control_t; +/* + * include/linux/sched.h, we add cabi_info address. + * this is the reference macros. + */ +#define TASK_ACCOUNT(tsk) ((cabi_account_t)((tsk)->cabi_info)) +#define LVAL_TASK_ACCOUNT(tsk) ((tsk)->cabi_info) +#define CABI_ID(tsk) ((unsigned long)((tsk)->cabi_info->cabi_id)) + +/* + * Internal data structure to keep track of cpu capacity usages. + */ +typedef unsigned long cpu_capacity_t; +typedef unsigned long long cpu_capacity_quad_t; + +#define CAPACITY_INT(x) ((x)/100) +#define CAPACITY_FRAC(x) ((x)-(x/100)*100) +#define INT2CAPACITY(x) ((x)*10000) +#define CAPACITY2INT(x) ((x)/10000) +#define PERCENT2CAPACITY(x) ((x)*100) +/* #define CAPACITY_OF(c,t) ((c)/CAPACITY2INT(t)) */ +#define CPU_CAPACITY_MAX PERCENT2CAPACITY(100) +#define FULLCAPACITY 100 + +/* + * Define the instructions for hooks + */ +#define NULL_INSTRUCTION 0x000 +#define WAKE_UP 0x001 +#define CAPACITY_CALCULATION 0x002 +#define LIMIT_CHECK 0x003 +#define OVERLOAD_CHECK 0x004 +#define ISR_EXPIRE 0x005 +#define PRIORITY_BOOST 0x006 +/* + * struct cabi_account + */ +struct cabi_account { + + cabi_account_state_t cpu_state; /* state */ + struct cpu_param pm; /* policy & operation */ + cabi_priority_control_t prio_type; /* type of the priority */ + int priority_boost, priority_depleted; /* priority boost */ + struct cabi_account_operations *ops; + + cabi_object_t cabi_id; /* object id */ + cabi_overload_t overload; /* overload flag */ + + /* Linux dependent part */ + struct list_head cpu_proc_list; /* list of processes */ + + /* procfs entry under /proc/cpu/ */ + struct proc_dir_entry *cpu_proc_entry; + struct proc_dir_entry *cpu_log_proc_entry; + struct timer_list cpu_replenish_tmr; + struct k_itimer cpu_replenish_ktimer; + struct hrtimer cpu_replenish_hrtmr; + + cpu_tick_data_t cpu_period_used_ticks; /* CPU ticks already used + in the current period */ + cpu_tick_data_t cpu_period_start_ticks; /* remember start ticks for + the current invocation */ + cpu_tick_data_t cpu_period_available_ticks; /* CPU ticks that can be + * used for this period */ + wait_queue_head_t depleted_wait; /* for enforcement */ + + /* execution statistics */ + cpu_tick_data_t cpu_period_prev_used_ticks; + cpu_tick_data_t cpu_total_used_ticks; + cpu_capacity_t cpu_max_utilization; + cpu_capacity_t cpu_min_utilization; + + struct { + unsigned long total_count; /* replenishment count */ + cpu_capacity_quad_t total_utils; /* sum of utilizations */ + unsigned long *history; /* history of the average */ + } cpu_average; + + /* static data */ + struct list_head cpu_link; /* link all cpu accounts */ + struct timespec cpu_time; + struct timespec cpu_period; + cpu_tick_data_t cpu_time_ticks; /* ticks for cpu_time */ + cpu_tick_data_t cpu_period_ticks; /* ticks for cpu_period */ + cpu_capacity_t cpu_capacity; /* requested capacity */ + + opt_state_t opt_state; + unsigned long block_count, signal_count; + int signal_block; +}; + +typedef struct cabi_account *cabi_account_t; + +#define NULL_ACCOUNT ((cabi_account_t)0) +#define NULL_UACCOUNT ((cabi_uaccount_t)0) +#define NULL_ACCOUNT_ID 0x0 + +/* Spin Lock & Unlock + * Usage: + * { + * unsigned long flags; + e cabi_spin_lock(flags); + * + * cabi_spin_unlock(flags); + * } + */ +extern spinlock_t cabi_lock; +#define cabi_spin_lock(flags) spin_lock_irqsave(&cabi_lock, flags) +#define cabi_spin_unlock(flags) spin_unlock_irqrestore(&cabi_lock, flags) + +/* + * timer for accounts: + * replenishment ... periodic + * expiration ... aperiodic + * + * - tmr_expire: holds an absolute time in CPU tick when its timer expires. + * - tmr_handler: keeps the pointer to a handler funcion which is called + * when its timer expires. + * + */ +extern void cabi_replenish_timer_init(cabi_account_t, cpu_tick_t); +extern void cabi_replenish_timer_cancel(cabi_account_t); +extern void cabi_enforce_timer_start(cabi_account_t, cpu_tick_t); +extern void cabi_enforce_timer_cancel(void); +extern void cabi_timer_start(void); +extern int cabi_send_signal(cabi_account_t, int, int); + +/* + * Global Variables and params + */ +extern cpu_tick_data_t cabi_timer_adjust; +extern cpu_tick_data_t cabi_cpu_ticks_jitter; +extern cpu_tick_data_t cabi_cpu_ticks_per_second; +//extern cpu_tick_data_t cabi_cpu_ticks_per_jiffy; +extern cabi_account_t cabi_current_account; + +#define CABI_USECS_PER_JIFFY (1000016L/HZ) /* 10000 (HZ=100) */ +#define CABI_NANOSECS_PER_JIFFY (1000016762L/HZ) /* 10000167 (HZ=100) */ + +/* + * Conversions + */ + + +static inline void +usec2tick(cpu_tick_t us, cpu_tick_t tick) +{ + + unsigned long rtick, rem; + cpu_tick_data_t usec = MICROSEC; + cpu_tick_data_t result; + + + result = (*us) * cabi_cpu_ticks_per_second; + + cabi_debug("multiple*ns: %llu\n", result); + cabi_debug("usec : %llu \n", usec); + + rtick = div_long_long_rem(result, usec, &rem); + + cabi_debug("div (64bit/32bit) result rtick %lu rem %lu\n", + rtick, rem); + + *tick = (cpu_tick_data_t) rtick; + + cabi_debug("tick %llu \n", *tick); + +} + +#include +static spinlock_t cal_lock = SPIN_LOCK_UNLOCKED; + +static inline void +nanosec2tick(cpu_tick_t ns, cpu_tick_t tick) +{ + cpu_tick_data_t nanosec = NANOSEC; + cpu_tick_data_t result; + unsigned long rtick, rem, cpu_sec, cpu_ns; + + spin_lock(&cal_lock); + + if (cabi_cpu_ticks_per_second > 1000000UL) { + cabi_debug("cabi_cpu_ticks_per_second is over %llu\n", + cabi_cpu_ticks_per_second); + + /* to avoid overflow of multiple of two values, + a * b / c transform a /c1 * b/c2 + in this case, nanosec is 1000000000, therefore + deviding by 100000(5) and 100000(4) then multiple + makes the same result */ + + /* cabi_cpu_ticks_per_secnd is devided by 100000 */ + cpu_sec = div_long_long_rem (cabi_cpu_ticks_per_second, + 100000, &rem); + cabi_debug("[1] cpu_sec : %lu\n", cpu_sec); + + /* ns is devided by 10000 */ + cpu_ns = div_long_long_rem (*ns, 10000, &rem); + cabi_debug("[2] cpu_ns : %lu\n", cpu_ns); + + rtick = cpu_sec * cpu_ns; + cabi_debug("[3] div (64bit/32bit) rtick %lu rem %lu\n", + rtick, rem); + + } else { + result = (*ns) * cabi_cpu_ticks_per_second; + cabi_debug("[1] multiple*ns: %llu\n", result); + rtick = div_long_long_rem(result, nanosec , &rem); + + cabi_debug("[2] div (64bit/32bit) rtick %lu rem %lu\n", + rtick, rem); + } + + *tick = (cpu_tick_data_t) rtick; + spin_unlock(&cal_lock); + + cabi_debug("[3] rtick-> tick %llu \n", *tick); +} + + + +static inline cpu_tick_data_t +_tick2nanosec(cpu_tick_t tick) +{ + cpu_tick_data_t nanosec = NANOSEC; + return ((*tick) * nanosec) / cabi_cpu_ticks_per_second; +} + + +static inline cpu_tick_data_t +tick2nanosec(cpu_tick_t tick) +{ + cpu_tick_data_t nanosec = NANOSEC; + cpu_tick_data_t us = MICROSEC; + cpu_tick_data_t ms = MILISEC; + unsigned long rem, rtick, cpu_sec; + cpu_tick_data_t cpu_tick; + + spin_lock(&cal_lock); + if (*tick > 100000000UL) { + cabi_debug("tick is over 100000000\n"); + + /* The formula is originally, + * ns * tick / cpu_ticks_pse + * (ns * tick)/us / cpu_ticks_pse/us + * = ms * tick / cpu_ticks_pse/us + */ + + cpu_tick = (*tick) * ms; + cpu_sec = div_long_long_rem + (cabi_cpu_ticks_per_second, us, &rem); + + cabi_debug("cpu_tick %llu cpu_sec %lu\n", + cpu_tick, cpu_sec); + + rtick = (unsigned long) div_long_long_rem + (cpu_tick, (unsigned long) cpu_sec, &rem); + + } else { + *tick = (*tick) * nanosec; + rtick = (unsigned long) div_long_long_rem + ((*tick), (unsigned long) cabi_cpu_ticks_per_second, &rem); + } + *tick = (unsigned long long) rtick; + spin_unlock(&cal_lock); + + cabi_debug("nanosec : tick %llu rem %lu\n", *tick, rem); + + return (*tick); +} + + +#ifndef CONFIG_X86 +static inline void +jiffies2tick(cpu_tick_t tick) +{ + unsigned long long milisec = MILISEC; + *tick = (jiffies * 10) * (cabi_cpu_ticks_per_second / milisec); +} +#endif /* #ifndef CONFIG_X86 */ + +static inline void +cabi_rdticks(cpu_tick_t data_p) +{ +#ifdef CONFIG_X86 + cabi_rdtsc(data_p); +#else + jiffies2tick(data_p); +#endif /* #ifdef CONFIG_X86 */ +} + +/* + * Conversion between tick and usec + * cabi_cpu_ticks_per_second:MICROSEC = ticks:usec + */ +static inline void +tick2usec(cpu_tick_t tick, cpu_tick_t us) +{ + cpu_tick_data_t usec = MICROSEC; + unsigned long rem, rtick, ctick; + + cabi_debug("[tick2usec:01] %llu\n", *tick); + + ctick = (unsigned long) div_long_long_rem + (cabi_cpu_ticks_per_second, (unsigned long)usec, &rem); + + if(*tick > 100000000UL) { + + rtick = (unsigned long) + div_long_long_rem ((*tick), ctick, &rem); + cabi_debug("[tick2usec:02] usec %lu rem %lu\n", rtick, rem); + + } else { + rtick = (*tick) / ctick; + cabi_debug("[tick2usec:03] usec %lu\n", rtick); + } + *us = (unsigned long) rtick; + +} + +static inline unsigned long +TICK2USEC(cpu_tick_t tick) +{ + cpu_tick_data_t us; + tick2usec(tick, &us); + return (unsigned long) us; +} + +static inline int +tick2ts(cpu_tick_t tick, struct timespec *ts) +{ + + cpu_tick_data_t ns; + cpu_tick_data_t ms = MILISEC; + unsigned long rtick, mtick, rem, cpu_sec; + + if (!tick) { + return CABI_EINVAL; + } + + cabi_debug("in tick2ts\n"); + cabi_debug("tick %llu / ticks_per_sec %llu\n", + (*tick), cabi_cpu_ticks_per_second); + + if (*tick > MICROSEC) { + mtick = div_long_long_rem + ((*tick), ms, &rem); + cpu_sec = div_long_long_rem + ((cabi_cpu_ticks_per_second), ms, &rem); + rtick = (unsigned long) div_long_long_rem + (mtick, (unsigned long) cpu_sec, &rem); + ts->tv_sec = rtick; + + cabi_debug("tv_sec %lu rem %lu\n", ts->tv_sec, rem); + ns = mtick - (cpu_sec * ts->tv_sec); + ns = ns*ms; + + cabi_debug("tick - (tv_sec*cpu_sec) = ns %llu\n", ns); + ts->tv_nsec = tick2nanosec(&ns); + + } else { + cabi_debug("tick is not over.\n"); + rtick = (unsigned long) div_long_long_rem + ((*tick), + (unsigned long) cabi_cpu_ticks_per_second, &rem); + ts->tv_sec = rtick; + cabi_debug("tv_sec %lu rem %lu\n", ts->tv_sec, rem); + + ns = *tick - (cabi_cpu_ticks_per_second * ts->tv_sec); + cabi_debug("tick - (tv_sec*cpu_sec) = ns %llu\n", ns); + + ts->tv_nsec = tick2nanosec(&ns); + } + cabi_debug("tv_nsec %lu\n", ts->tv_nsec); +} + +/* + * Name : cabi_account_summation_of_used_ticks + * + * This function called from stop_account() function which has to tally + * their used time. + */ + +static inline void +cabi_account_summation_of_used_ticks(cabi_account_t cabi, cpu_tick_t now) +{ + cabi->cpu_period_used_ticks += (*now - cabi->cpu_period_start_ticks); + cabi->cpu_period_start_ticks = *now; +} + +static inline unsigned long long +cabi_subtract_ll (unsigned long x, unsigned long y, + cabi_account_t cabi) +{ + unsigned long long available, used, pulled; + unsigned long rem; + + available = x; + used = y; + + available = (unsigned long) div_long_long_rem + (cabi->cpu_period_available_ticks, + MILISEC, &rem); + used = (unsigned long) div_long_long_rem + (cabi->cpu_period_used_ticks, + MILISEC, &rem); + pulled = (available - used) * MILISEC; + + return pulled; +} + + +/* + * Enable/Disable CABI hooks + */ +static void inline +cabi_enable(void) +{ + extern void cabi_enable_schedule_cpu(void); + extern void cabi_enable_isr(void); + + cabi_enable_schedule_cpu(); + cabi_enable_isr(); +} + +static void inline +cabi_disable(void) +{ + extern void cabi_disable_schedule_cpu(void); + extern void cabi_disable_isr(void); + + cabi_disable_schedule_cpu(); + cabi_disable_isr(); +} + +/* + * Start/Stop accounting + */ +void cabi_start_account(cabi_account_t); +void cabi_stop_account(cabi_account_t, cpu_tick_t); +void cabi_account_enforce(cabi_account_t); +void cabi_account_replenish(cabi_account_t); +extern void cabi_account_sleep_on(cabi_account_t); + +/* proc file systems */ +extern int cabi_account_read_proc(cabi_account_t, char *); +extern int cabi_account_read_bindpid_proc(cabi_account_t, char *); +extern int cabi_account_read_block_proc(cabi_account_t, char *); +extern int cabi_account_read_time_proc(cabi_account_t, char *); + +static inline int +cabi_account_depleted(cabi_account_t cabi) +{ + if (cabi) { + return (cabi->cpu_state & CABI_IS_DEPLETED); + } + return 0; +} + +extern void cabi_proc_account_create(cabi_account_t); +extern void cabi_proc_account_destroy(cabi_account_t); + +/* + * for overload monitoring. + */ +extern int setup_overload_id (cabi_account_t cabi); +extern int cabi_account_check_overload(void); +extern void capacity_overload (struct timespec *, struct timespec *, + cpu_capacity_quad_t *); + +static inline int +cabi_account_overload(cabi_account_t cabi) +{ + if (cabi) { + if (cabi->overload == CABI_IS_OVERLOAD) { + cabi_debug("CABI_IS_OVERLOAD\n"); + return 1; + } + } + return 0; +} + +/* cabi_account.c */ +extern cabi_account_t search_cabi(cabi_object_t); +extern int cabi_account_attach (unsigned long, + struct task_struct *); +extern int cabi_account_detach (struct task_struct *); + +extern cpu_capacity_t capacity_of (cpu_capacity_quad_t, cpu_capacity_quad_t); + +extern cabi_account_t cabi_account_create (struct timespec *, struct timespec *, + cabi_param_data_t *); +extern int cabi_account_set (unsigned long, struct timespec *, + struct timespec *, cabi_param_data_t *); +extern int cabi_account_destroy (unsigned long); + +extern void capacity_calculation (cabi_account_t); +extern int capacity_admission_control(cabi_param_data_t *p, unsigned long capacity); + +extern void cabi_account_sleep_on (cabi_account_t); +extern int cabi_boost_priority (cabi_account_t); +extern void cpu_time_replenish_init(cabi_account_t); +extern void check_sched_param (struct rs_proc_list *rs_proc); + +/* operations */ +extern void set_terminate_operation (cabi_account_t); +extern void set_account_policy (cabi_account_t); + +extern struct cabi_account_operations cyclic_ops; +extern struct cabi_account_operations dsv_ops; +extern struct cabi_account_operations ovl_ops; + + +struct cabi_account_operations { + void (*replenish) (cabi_account_t); + void (*isr) (cabi_account_t); + void (*isr_operation) (cabi_account_t); + void (*isr_priority) (cabi_account_t); +}; + +/* + * Scheduling type + */ +#define LINUX_RT_PRIORITY 50 /* used with SCHED_FIFO */ +#define LINUX_TS_PRIORITY 0 +#define CABI_RT_MAX_PRIORITY 60 + +/* + * Process list + */ +struct rs_proc_list { + struct list_head rs_proc_list; + pid_t rs_proc_pid; + struct task_struct *rs_proc_task; +}; + +static inline void +rs_proc_list_apply(struct list_head *proc_list_head, + void (*func) (struct rs_proc_list *)) +{ + struct list_head *proc_list; + struct rs_proc_list *rs_proc; + + proc_list = proc_list_head->next; + while (proc_list != proc_list_head) { + /* get a rs_proc */ + rs_proc = + list_entry(proc_list, struct rs_proc_list, rs_proc_list); + /* do it */ + func(rs_proc); + + /* next process */ + proc_list = proc_list->next; + } +} + +#define malloc(s) kmalloc(s, SLAB_KERNEL) +#define free(p) kfree(p) +#define bzero(p, s) memset(p, 0, s) + +extern void cabi_account_sched_rt(struct rs_proc_list *); +extern void cabi_account_sched_ts(struct rs_proc_list *); +extern struct task_struct * find_idle_process(void); + +static inline struct task_struct * +__cabi_find_process_by_pid(pid_t pid) +{ + struct task_struct *tsk = current; + + if (pid) + tsk = find_task_by_pid(pid); + return tsk; +} + +static inline struct task_struct * +__cabi_find_idle_process(pid_t pid) +{ + struct task_struct *idle; + + /* if (pid == 0) */ + idle = find_idle_process(); + if (!idle) { + idle = NULL; + return idle; + } else { + return idle; + } +} + +#else /* __KERNEL__ */ + +/* + * Types for user level applications. + */ +typedef void *cabi_account_t; +#define NULL_ACCOUNT 0 + +/* + * Function prototypes, + */ +extern int cabi_account_create(struct cabi_uaccount *); +extern int cabi_account_destroy(unsigned long); +extern int cabi_account_bind_pid(unsigned long, pid_t); +extern int cabi_account_bind_pgid(unsigned long cabi_id, pid_t pgid); +extern int cabi_account_unbind(pid_t); +extern int cabi_account_get(unsigned long, cabi_uaccount_t); +extern int cabi_account_set(unsigned long, cabi_uaccount_t); +/* + * library call + */ +extern int cabi_overload_create(struct cabi_uaccount *); +extern int cabi_overload_destroy(void); +extern int cabi_create_bind(struct cabi_uaccount *, pid_t); + + +#endif /* __KERNEL__ */ + + +#endif diff -urN ./linux-2.6.18.1/include/cabi/cabi_debug.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/cabi_debug.h --- ./linux-2.6.18.1/include/cabi/cabi_debug.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/cabi_debug.h 2007-05-23 19:37:52.000000000 +0900 @@ -0,0 +1,215 @@ +/* + * Debug header of CABI + */ +#ifndef CABI_DEBUG_H +#define CABI_DEBUG_H + +#include +#include +#include + + +/* + * Please change the definie to undef if you don't need to + * printk the debug codes. + */ +/* + * Define CABI_DEBUG to produce debug message to console + */ +#undef CABI_DEBUG +#define CABI_TEST 1 + +/* + * The CABI version + */ +#define CABI_DATE "07/05/05" +#define CABI_VERSION "0.5a" + +/* + * Debug code + */ +/* assrt with traditional prinf/panic */ +#ifdef CONFIG_KERNEL_ASSERTS +/* kgdb stuff */ +#define assert(p) KERNEL_ASSERT(#p, p) +#else +#define assert(p) do { \ + if (!(p)) { \ + printk(KERN_CRIT "BUG at %s:%d assert(%s)\n", \ + __FILE__, __LINE__, #p); \ + BUG(); \ + } \ +} while (0) +#endif + +/* + * the general debug interface for cabi + */ + +#ifdef CABI_DEBUG +#define cabi_debug(fmt, arg...) \ + printk(KERN_NOTICE " " __FILE__": " fmt "" , ## arg) +#else +#define cabi_debug(fmt, arg...) +#endif + +#ifdef CABI_DEBUG +#define ENTER \ + cabi_debug("ENTER [%s;%d] \n", __FUNCTION__, __LINE__); +#define EXIT \ + cabi_debug("EXIT [%s:%d] \n", __FUNCTION__,__LINE__); + +#define CABI_DBG \ + cabi_debug("DBG [%s:%d] \n", __FUNCTION__,__LINE__); + +#else + +#define ENTER +#define EXIT +#define CDEBUG +#define CABI_DBG +#define CABI_DBG_AO +#define CABI_DBG_TIMESPEC +#define CABI_DBG_TG +#define CABI_WARNING +#define CABI_NOTICE +#define CABI_DEBUGX + +#endif // CABI_DEBUG + +/* + * Define CABI_TEST to produce cycle counter values to specific buffer. + */ +#ifdef CABI_TEST + +#define cabi_test(fmt, arg...) \ + printk(KERN_NOTICE "" fmt "" , ## arg) +#define MAX_BUF_LEN 1024 + +extern char cabip[MAX_BUF_LEN]; +extern int cabi_len; +extern int cabi_debug_counter; + +static inline void cabi_eval_rdtsc (unsigned long long *data_p) +{ + rdtscll(*data_p); +} +static inline unsigned long long cabi_show_rdtsc(void) +{ + unsigned long long now; + cabi_eval_rdtsc (&now); + return now; +} +static inline void +cabi_print_enter (void) +{ + unsigned long long now; + + cabi_eval_rdtsc(&now); + cabi_len += sprintf (cabip+cabi_len, "%llu\n", now); +} + +static inline void +cabi_print_exit (void) +{ + unsigned long long now; + + cabi_eval_rdtsc(&now); + cabi_len += sprintf (cabip+cabi_len, "EXIT %llu %s %s \n", + now, __FILE__, __FUNCTION__); + +} +#define TENTER \ + cabi_test ("ENTER [%s:%d] %llu\n", __FUNCTION__, __LINE__, \ + cabi_show_rdtsc()); +#define TEXIT \ + cabi_test ("EXIT [%s:%d] %llu\n", __FUNCTION__, __LINE__, \ + cabi_show_rdtsc()); +/* +#define cabi_dump \ +do { \ + cabi_len += sprintf(cabip+cabi_len, "[%s:%d] %llu %d\n", __FUNCTION__,__LINE__, cabi_show_rdtsc(), cabi_debug_counter++); \ +} while(0) +*/ + +#else +#define TENTER +#define TEXIT +#endif + + +/* + * Debug functions + */ + + +/* extern parameters */ +extern struct cabi_uaccount *ucabi; +extern struct cpu_param *p; +extern struct cabi_account *cabi; +extern struct rs_proc_list *rs_proc; +extern struct timer_list *tmr; + +/* sanity_check_functions */ +extern int cabi_sanity_check_timespec_c_and_t (struct timespec *c, struct timespec *t); +extern int cabi_sanity_check_overload_id (void); +extern int cabi_sanity_check_ucabi (struct cabi_uaccount *ucabi); +extern int cabi_sanity_check_term_act (struct cabi_uaccount *ucabi); +extern void cabi_sanity_check_parameter_to_copy (struct timespec *c, struct timespec *t, struct cpu_param *p); +extern int cabi_sanity_check_operation (struct cabi_uaccount *ucabi); +extern void cabi_debug_timespecs (struct timespec *c, struct timespec *t); +extern void cabi_debug_timespec (struct timespec *t); +extern int cabi_sanity_check_sigoperation (struct cabi_uaccount *ucabi); + +/* just logging the values */ +extern void cabi_debug_capacity (unsigned long capacity); +extern void cabi_debug_ticks (struct cabi_account *); +extern void cabi_debug_ct (unsigned long long, unsigned long long); +extern void cabi_debug_sig_param(struct cabi_account *); + +extern int pid_check(pid_t); +extern void bind_pid_error(pid_t); +extern void cabi_account_attached(void); +extern int pgid_check(pid_t); +extern int cabi_id_check(unsigned long); + +extern void cabi_debug_info (struct cabi_account *); +extern void cabi_debug_state (struct cabi_account *); +extern void cabi_debug_detach (struct rs_proc_list *); +extern void cabi_debug_ticks (struct cabi_account *); +extern void cabi_debug_tick (unsigned long long tick); +extern void cabi_debug_avail_ticks (struct cabi_account *); + +/* cabi_isr.c */ +extern void cabi_debug_current(struct cabi_account *); + +/* cabi_sched.c */ +extern void cabi_debug_entities (struct cabi_account *, + struct cabi_account *); +/* kernel/sched.c */ +extern void cabi_debug_ksched (struct task_struct *, + struct task_struct *); +/* cabi_signal.c */ +extern void cabi_debug_signal_pid (int); +extern void cabi_debug_signal_attrs (int, int, struct task_struct *tsk); + +/* cabi_timer.c */ +extern void cabi_debug_times (struct timer_list *tmr, unsigned long); +extern void cabi_debug_timer (struct timer_list *tmr); + +extern void check_hrtimer_res (void); +extern void check_rep_expires (ktime_t); +extern void check_enf_expires (ktime_t); +extern void check_exstate (ktime_t, struct cabi_account *); +extern void check_cancel (int); + +/* */ +extern void cabi_dump (int); +extern void cabi_dump_ex (int, struct task_struct *, + struct cabi_account *); +extern int cabi_dump_init (void); +extern void cabi_dump_read (int); +extern void cabi_dump_end (void); +extern void cabi_dump_sched (int, struct task_struct *); + +#endif /* CABI_DEBUG_H */ diff -urN ./linux-2.6.18.1/include/cabi/cabi_error.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/cabi_error.h --- ./linux-2.6.18.1/include/cabi/cabi_error.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/cabi_error.h 2007-01-09 23:15:54.000000000 +0900 @@ -0,0 +1,23 @@ +#ifndef CABI_CABI_ERROR_H +#define CABI_CABI_ERROR_H + +#define CABI_SUCCESS 0 /* Success */ +#define CABI_ERROR 1 /* Error */ + +#define CABI_SYSERR 2 /* Linux system error */ +#define CABI_EINVAL 3 /* Invalid argument */ +#define CABI_EACCESS 4 /* No use authority */ + +#define CABI_ENOMEM 5 /* Memory allocation failed. */ +#define CABI_EATTACHED 6 /* Process is still attached. */ +#define CABI_ENOAVLE 7 /* PID is registered into another AO. */ +#define CABI_EREGIST 8 /* PID is already registered into AO. */ +#define CABI_ENOBIND 9 /* PID is not bound to AO. */ +#define CABI_ENOEXIST 10 /* AO dose not exist. */ +#define CABI_EPNOEXIST 11 /* PID dose not exist. */ +#define CABI_EPGNOEXIST 12 /* PGID dose not exist. */ +#define CABI_ENOCABIID 13 /* No more cabi id exist. */ + +#define CABI_CREATE_ERR 14 /* cabi_account_create error. */ + +#endif /* CABI_CABI_ERROR_H */ diff -urN ./linux-2.6.18.1/include/cabi/unistd.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/unistd.h --- ./linux-2.6.18.1/include/cabi/unistd.h 1970-01-01 09:00:00.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/cabi/unistd.h 2007-05-06 11:22:31.000000000 +0900 @@ -0,0 +1,118 @@ +#ifndef _ASM_I386_CABI_UNISTD_H_ +#define _ASM_I386_CABI_UNISTD_H_ + +/* + * This file contains the system call numbers. + */ + +#ifdef CONFIG_CABI +#define __NR_cabi_account_create 318 +#define __NR_cabi_account_destroy 319 +#define __NR_cabi_account_bind_pid 320 +#define __NR_cabi_account_bind_pgid 321 +#define __NR_cabi_account_unbind 322 +#define __NR_cabi_account_get 323 +#define __NR_cabi_account_set 324 +#define __NR_cabi_account_eval 325 +#endif + + +/* + * user-visible error numbers are in the range -1 - -128: see + * + */ +#define __syscall_return(type, res) \ +do { \ + if ((unsigned long)(res) >= (unsigned long)(-(128 + 1))) { \ + errno = -(res); \ + res = -1; \ + } \ + return (type) (res); \ +} while (0) + +/* XXX - _foo needs to be __foo, while __NR_bar could be _NR_bar. */ +#define _syscall0(type,name) \ +type name(void) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name)); \ +__syscall_return(type,__res); \ +} + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"ri" ((long)(arg1)) : "memory"); \ +__syscall_return(type,__res); \ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2) \ +type name(type1 arg1,type2 arg2) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)) \ + : "memory"); \ +__syscall_return(type,__res); \ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ +type name(type1 arg1,type2 arg2,type3 arg3) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)) : "memory"); \ +__syscall_return(type,__res); \ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \ +type name (type1 arg1, type2 arg2, type3 arg3, type4 arg4) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx" \ + : "=a" (__res) \ + : "0" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)) : "memory"); \ +__syscall_return(type,__res); \ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ +{ \ +long __res; \ +__asm__ volatile ("push %%ebx ; movl %2,%%ebx ; movl %1,%%eax ; " \ + "int $0x80 ; pop %%ebx" \ + : "=a" (__res) \ + : "i" (__NR_##name),"ri" ((long)(arg1)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ + : "memory"); \ +__syscall_return(type,__res); \ +} + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ +long __res; \ + struct { long __a1; long __a6; } __s = { (long)arg1, (long)arg6 }; \ +__asm__ volatile ("push %%ebp ; push %%ebx ; movl 4(%2),%%ebp ; " \ + "movl 0(%2),%%ebx ; movl %1,%%eax ; int $0x80 ; " \ + "pop %%ebx ; pop %%ebp" \ + : "=a" (__res) \ + : "i" (__NR_##name),"0" ((long)(&__s)),"c" ((long)(arg2)), \ + "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)) \ + : "memory"); \ +__syscall_return(type,__res); \ +} + + +#endif /* _ASM_I386_UNISTD_H_ */ バイナリー・ファイル./linux-2.6.18.1/include/linux/.kprobes.h.swpとlinux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/.kprobes.h.swpは違います diff -urN ./linux-2.6.18.1/include/linux/hrtimer.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/hrtimer.h --- ./linux-2.6.18.1/include/linux/hrtimer.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/hrtimer.h 2007-05-22 17:38:09.000000000 +0900 @@ -54,6 +54,9 @@ ktime_t expires; int (*function)(struct hrtimer *); struct hrtimer_base *base; +#ifdef CONFIG_CABI + char *data; +#endif }; /** diff -urN ./linux-2.6.18.1/include/linux/init_task.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/init_task.h --- ./linux-2.6.18.1/include/linux/init_task.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/init_task.h 2007-01-09 23:15:48.000000000 +0900 @@ -6,6 +6,10 @@ #include #include +#ifdef CONFIG_CABI +#include +#endif + #define INIT_FDTABLE \ { \ .max_fds = NR_OPEN_DEFAULT, \ @@ -128,6 +132,7 @@ .pi_lock = SPIN_LOCK_UNLOCKED, \ INIT_TRACE_IRQFLAGS \ INIT_LOCKDEP \ + .cabi_info = NULL, \ } diff -urN ./linux-2.6.18.1/include/linux/sched.h linux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/sched.h --- ./linux-2.6.18.1/include/linux/sched.h 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/include/linux/sched.h 2007-01-09 23:15:48.000000000 +0900 @@ -945,7 +945,10 @@ /* journalling filesystem info */ void *journal_info; - + +/* CPU Accounting System info */ + void *cabi_info; + /* VM state */ struct reclaim_state *reclaim_state; diff -urN ./linux-2.6.18.1/init/main.c linux-2.6.18.1-cabi-20070524-hrt-nrt/init/main.c --- ./linux-2.6.18.1/init/main.c 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/init/main.c 2007-01-09 23:15:25.000000000 +0900 @@ -62,6 +62,10 @@ #include #endif +#ifdef CONFIG_CABI +extern void cabi_init(void); +#endif + /* * This is one of the first .c files built. Error out early if we have compiler * trouble. @@ -661,6 +665,10 @@ sysctl_init(); #endif +#ifdef CONFIG_CABI + cabi_init(); +#endif + do_initcalls(); } diff -urN ./linux-2.6.18.1/kernel/exit.c linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/exit.c --- ./linux-2.6.18.1/kernel/exit.c 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/exit.c 2007-01-09 23:15:27.000000000 +0900 @@ -921,6 +921,17 @@ cpuset_exit(tsk); exit_keys(tsk); +#ifdef CONFIG_CABI + if (tsk->cabi_info) { + extern void cabi_account_detach(struct task_struct *); +#ifdef DEBUG_CABI + printk("in exit, detach pid (%d) cabi(0x%x)\n", + tsk->pid, (int) tsk->cabi_info); +#endif + cabi_account_detach(tsk); + } +#endif + if (group_dead && tsk->signal->leader) disassociate_ctty(1); diff -urN ./linux-2.6.18.1/kernel/fork.c linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/fork.c --- ./linux-2.6.18.1/kernel/fork.c 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/fork.c 2007-06-17 00:20:22.000000000 +0900 @@ -3,7 +3,6 @@ * * Copyright (C) 1991, 1992 Linus Torvalds */ - /* * 'fork.c' contains the help-routines for the 'fork' system call * (see also entry.S and others). @@ -53,6 +52,10 @@ #include #include +#ifdef CONFIG_CABI +#include +#endif + /* * Protected counters by write_lock_irq(&tasklist_lock) */ @@ -1201,6 +1204,20 @@ goto bad_fork_cleanup_namespace; } +#ifdef CONFIG_CABI + if (p->cabi_info) { + cabi_account_t cabi; + int cabi_account_attach(unsigned long, struct task_struct *); + cabi = p->cabi_info; + p->cabi_info = NULL; + cabi_account_attach(cabi->cabi_id, p); +#ifdef DEBUG_CABI + printk("in fork, attach pid(%d), cabi(0x%x)\n", + p->pid, (int) cabi); +#endif + } +#endif + if (clone_flags & CLONE_THREAD) { p->group_leader = current->group_leader; list_add_tail_rcu(&p->thread_group, &p->group_leader->thread_group); diff -urN ./linux-2.6.18.1/kernel/hrtimer.c linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/hrtimer.c --- ./linux-2.6.18.1/kernel/hrtimer.c 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/hrtimer.c 2007-05-22 21:10:10.000000000 +0900 @@ -642,15 +642,23 @@ /* * Called from timer softirq every jiffy, expire hrtimers: */ + void hrtimer_run_queues(void) { + struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); int i; +//doly backport + +// printk("hrtimer_run_queues\n"); hrtimer_get_softirq_time(base); + spin_lock(base->lock); for (i = 0; i < MAX_HRTIMER_BASES; i++) run_hrtimer_queue(&base[i]); + + spin_unlock(base->lock); } /* diff -urN ./linux-2.6.18.1/kernel/sched.c linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/sched.c --- ./linux-2.6.18.1/kernel/sched.c 2006-10-14 12:34:03.000000000 +0900 +++ linux-2.6.18.1-cabi-20070524-hrt-nrt/kernel/sched.c 2007-06-16 23:56:48.000000000 +0900 @@ -55,6 +55,10 @@ #include #include +#ifdef CONFIG_CABI +#include +#include +#endif /* * Convert user-nice values [ -20 ... 0 ... 19 ] @@ -758,6 +762,8 @@ static void set_load_weight(struct task_struct *p) { + ENTER; + if (has_rt_policy(p)) { #ifdef CONFIG_SMP if (p == task_rq(p)->migration_thread) @@ -772,6 +778,8 @@ p->load_weight = RTPRIO_TO_LOAD_WEIGHT(p->rt_priority); } else p->load_weight = PRIO_TO_LOAD_WEIGHT(p->static_prio); + + cabi_debug("[setload weight] %d\n", p->load_weight); } static inline void @@ -3288,6 +3296,29 @@ sleep_type == SLEEP_INTERRUPTED); } +#ifdef CONFIG_CABI +struct task_struct * find_idle_process(void) +{ + return idle_task(smp_processor_id()); +} + +static inline void cabi_sched_check (struct task_struct *prev, struct task_struct *next) +{ + + /* proto type */ + extern void (*cabi_schedule_hook) + (struct task_struct *prev, struct task_struct *next); + + /* debug */ + cabi_debug_ksched(prev, next); + + /* set hook */ + if (cabi_schedule_hook) + cabi_schedule_hook(prev, next); +} +#endif + + /* * schedule() is the main scheduler function. */ @@ -3301,7 +3332,6 @@ int cpu, idx, new_prio; long *switch_count; struct rq *rq; - /* * Test if we are atomic. Since do_exit() needs to call into * schedule() atomically, we ignore that path for now. @@ -3427,6 +3457,10 @@ prev->sleep_avg = 0; prev->timestamp = prev->last_ran = now; +#ifdef CONFIG_CABI + cabi_sched_check(prev,next); +#endif + sched_info_switch(prev, next); if (likely(prev != next)) { next->timestamp = now; @@ -3435,6 +3469,7 @@ ++*switch_count; prepare_task_switch(rq, next); + prev = context_switch(rq, prev, next); barrier(); /* @@ -3452,6 +3487,7 @@ preempt_enable_no_resched(); if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) goto need_resched; + } EXPORT_SYMBOL(schedule); @@ -4059,11 +4095,21 @@ /* Actually do priority change: must hold rq lock. */ static void __setscheduler(struct task_struct *p, int policy, int prio) { + + ENTER; BUG_ON(p->array); + CABI_DBG; + p->policy = policy; p->rt_priority = prio; p->normal_prio = normal_prio(p); + cabi_debug("[__setsched] policy %d rt_priority %d " + "normal_prio %d\n", + p->policy, + p->rt_priority, + p->normal_prio); + /* we are holding p->pi_lock already */ p->prio = rt_mutex_getprio(p); /* @@ -4074,6 +4120,7 @@ set_load_weight(p); } +#include /** * sched_setscheduler - change the scheduling policy and/or RT priority of * a thread. @@ -4091,6 +4138,8 @@ /* may grab non-irq protected spin_locks */ BUG_ON(in_interrupt()); + + recheck: /* double check policy once rq lock held */ if (policy < 0) @@ -4098,11 +4147,12 @@ else if (policy != SCHED_FIFO && policy != SCHED_RR && policy != SCHED_NORMAL && policy != SCHED_BATCH) return -EINVAL; - /* - * Valid priorities for SCHED_FIFO and SCHED_RR are - * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and - * SCHED_BATCH is 0. - */ + + /* + * Valid priorities for SCHED_FIFO and SCHED_RR are + * 1..MAX_USER_RT_PRIO-1, valid priority for SCHED_NORMAL and + * SCHED_BATCH is 0. + */ if (param->sched_priority < 0 || (p->mm && param->sched_priority > MAX_USER_RT_PRIO-1) || (!p->mm && param->sched_priority > MAX_RT_PRIO-1)) @@ -4111,19 +4161,20 @@ != (param->sched_priority == 0)) return -EINVAL; - /* - * Allow unprivileged RT tasks to decrease priority: - */ + + /* + * Allow unprivileged RT tasks to decrease priority: + */ if (!capable(CAP_SYS_NICE)) { - /* - * can't change policy, except between SCHED_NORMAL - * and SCHED_BATCH: - */ + /* + * can't change policy, except between SCHED_NORMAL + * and SCHED_BATCH: + */ if (((policy != SCHED_NORMAL && p->policy != SCHED_BATCH) && (policy != SCHED_BATCH && p->policy != SCHED_NORMAL)) && !p->signal->rlim[RLIMIT_RTPRIO].rlim_cur) return -EPERM; - /* can't increase priority */ + /* can't increase priority */ if ((policy != SCHED_NORMAL && policy != SCHED_BATCH) && param->sched_priority > p->rt_priority && param->sched_priority > @@ -4134,7 +4185,7 @@ (current->euid != p->uid)) return -EPERM; } - + retval = security_task_setscheduler(p, policy, param); if (retval) return retval; @@ -4148,7 +4199,7 @@ * runqueue lock must be held. */ rq = __task_rq_lock(p); - /* recheck policy now with rq lock held */ + /* recheck policy now with rq lock held */ if (unlikely(oldpolicy != -1 && oldpolicy != p->policy)) { policy = oldpolicy = -1; __task_rq_unlock(rq); @@ -4156,10 +4207,15 @@ goto recheck; } array = p->array; + if (array) deactivate_task(p, rq); + oldprio = p->prio; + __setscheduler(p, policy, param->sched_priority); + + if (array) { __activate_task(p, rq); /* @@ -4173,12 +4229,14 @@ } else if (TASK_PREEMPTS_CURR(p, rq)) resched_task(rq->curr); } + __task_rq_unlock(rq); spin_unlock_irqrestore(&p->pi_lock, flags); - + rt_mutex_adjust_pi(p); return 0; + } EXPORT_SYMBOL_GPL(sched_setscheduler);