diff options
author | Quinn Jensen <quinn.jensen@freescale.com> | 2007-04-04 17:22:48 -0600 |
---|---|---|
committer | root <root@traveler.zdomain.com> | 2007-04-04 17:22:48 -0600 |
commit | 5ad8a10f75d4d232c3151dd43c70a00381e2fb81 (patch) | |
tree | db7f10e975c4c0db09dfad8ce54a3e6d4022fe7a /kernel | |
parent | 1e191d5402beb371e7901d62acf0eb031ec968ac (diff) |
Adds CodeTEST support to the Linux kernel.
http://www.bitshrine.org/gpp/linux-2.6.19.2-mx-codetest.patch
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/Makefile | 1 | ||||
-rw-r--r-- | kernel/codetest.c | 715 | ||||
-rw-r--r-- | kernel/ctswic.h | 41 | ||||
-rw-r--r-- | kernel/exit.c | 11 | ||||
-rw-r--r-- | kernel/fork.c | 8 | ||||
-rw-r--r-- | kernel/sched.c | 17 |
6 files changed, 793 insertions, 0 deletions
diff --git a/kernel/Makefile b/kernel/Makefile index 5e3f3b75563a..a974fb23d1da 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_RELAY) += relay.o obj-$(CONFIG_UTS_NS) += utsname.o obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o +obj-$(CONFIG_CODETEST) += codetest.o ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y) # According to Alan Modra <alan@linuxcare.com.au>, the -fno-omit-frame-pointer is diff --git a/kernel/codetest.c b/kernel/codetest.c new file mode 100644 index 000000000000..5bdf64df21a2 --- /dev/null +++ b/kernel/codetest.c @@ -0,0 +1,715 @@ +/* +-------------------------------------------------------------------------------| +| +| codetest.c - Linux implementation of CodeTEST RTOS event hooks +| +| Copyright (c) 2003 - 2005 Freescale Semiconductor, Inc. +| +| This software is licensed under the GPL. It may be redistributed +| and/or modified under the terms of the GNU General Public License as +| published by the Free Software Foundation; either version 2 of the +| License, or (at your option) any later version. +| +| Module version: Revision: 1.11 +| +-------------------------------------------------------------------------------| +*/ + +#include <linux/kernel.h> +#include <asm/io.h> +#include <asm/page.h> +#include <linux/sched.h> +#include <asm/current.h> +#include <linux/module.h> +#include <linux/string.h> +#include <asm/system.h> +#include <linux/mm.h> +#include <asm/pgalloc.h> +#include <linux/autoconf.h> +#ifdef CONFIG_ARM +#include <linux/time.h> +#endif + +/* +** HWIC definitions +*/ +#define CT_TASK_CREATE (0x2a100000) +#define CT_TASK_ENTER (0x2a200000) +#define CT_TASK_DELETE (0x2a300000) +#define CT_TASK_EXIT (0x2a400000) +#define CT_ISR_ENTER (0x2a500000) +#define CT_ISR_EXIT (0x2a600000) + +#define CT_TASK_NAMES (0x00020000) +#define CT_TASK_IDS (0x00010000) +#define CT_TPP_OVERRUN_TAG (0x2c400000) + +#ifdef CONFIG_CT_USEPCI +#include <linux/pci.h> + +#ifdef CodeTEST +#pragma no_tagging ctTag +#endif + +#define CT_VENDOR_ID (0x11ab) +#define CT_DEVICE_ID (0xf007) + +enum { + CT_BAR_0, + CT_BAR_1, + CT_BAR_2, + CT_BAR_3, + CT_BAR_4, + CT_BAR_5, + CT_NUM_RESOURCES +}; + +#endif /* CONFIG_CT_USEPCI */ + +volatile unsigned long *ct_ctrl_port_ptr = NULL; +volatile unsigned long *ct_data_port_ptr = NULL; +void ct_enable_pid_task_name(void); +void ct_disable_pid_task_name(void); +void ct_enable_hooks(void); +void ct_disable_hooks(void); +extern unsigned long ct_get_phys_addr(void); +extern void ct_set_phys_addr(unsigned long addr); +int ctTag(unsigned long); +int ctDataTag(unsigned long tagID); + +#ifndef CONFIG_CT_HOOKS_ENABLED +#define CONFIG_CT_HOOKS_ENABLED (0) +#endif + +#ifdef CONFIG_CT_USEMICTOR +#define CT_PHYS_ADDR CONFIG_CT_ADDR +#else +#define CT_PHYS_ADDR 0 +#endif + +#ifndef CONFIG_CT_BIG_ENDIAN +#define _LITTLE_ENDIAN +#endif + +static unsigned long ct_phys_addr = CT_PHYS_ADDR; +static unsigned long ct_hooks_enabled = CONFIG_CT_HOOKS_ENABLED; + +unsigned ct_pid_task_name_enabled = 0; +/* +** SWIC definitions +*/ +#include "ctswic.h" + +/* the kernel event tags are placed in SWIC buffer*/ +unsigned ct_swic_enabled = 0; +/* the ISR event tags are ignored */ +unsigned ct_filter_events = 1; +/* DEBUG - force tags output to HWIC ports when SWIC enabled */ +unsigned ct_force_hwic_enabled = 0; +/* reference to ring buffer defined in ctdriver */ +struct Hook_Buffer *ct_hook_buffer = NULL; + +static spinlock_t hook_buffer_lock = SPIN_LOCK_UNLOCKED; +static unsigned long lock_flags; + +#define HI_BIT_ONLY 0x80000000 +#define HOOK_INC(x) ((x) = (((x)+1) & (HOOK_BUFFER_SIZE-1))) + +unsigned task_tag_count = 0; +static unsigned dropped = 0; +static pid_t deleted_thread_id = -1; + +typedef unsigned long long U64; + +void ctWriteSWICTaskTags(unsigned n_dtags, const u32 dtags[], u32 tag); +int ct_encode_taskname(const char *name, u32 buffer[8], u32 pid); +u32 ctTagClock(void); + +EXPORT_SYMBOL(ct_enable_pid_task_name); +EXPORT_SYMBOL(ct_disable_pid_task_name); + +/* HWIC kernel exports */ +EXPORT_SYMBOL(ct_enable_hooks); +EXPORT_SYMBOL(ct_disable_hooks); +EXPORT_SYMBOL(ct_get_phys_addr); +EXPORT_SYMBOL(ct_set_phys_addr); +EXPORT_SYMBOL(ctTag); +EXPORT_SYMBOL(ctDataTag); + +/* SWIC kernel exports */ +EXPORT_SYMBOL(ct_swic_enabled); +EXPORT_SYMBOL(ct_filter_events); +EXPORT_SYMBOL(ct_force_hwic_enabled); +EXPORT_SYMBOL(ct_hook_buffer); + +/* +-------------------------------------------------------------------------------| +| +| ct_init() - perform physical -> kernel virtual mapping for the tag ports +| +-------------------------------------------------------------------------------| +*/ +int ct_init(void) +{ +#ifdef CONFIG_CT_USEPCI + struct pci_dev *ct; + static int printed = 0; +#endif + + /* + ** Check to see if the tag pointers have been initialized + */ + if (ct_ctrl_port_ptr == NULL) { +#ifdef CONFIG_CT_USEPCI + /* + ** Check to see if the CodeTEST PCI adapter has been found + */ + if ((ct = pci_find_device(CT_VENDOR_ID, CT_DEVICE_ID, 0)) == 0) { + /* + ** Be polite and only print once every 4 billion tries + */ + if (!printed++) { + printk("CODETEST: PCI device not located\n"); + } + return -1; + } + if (pci_enable_device(ct) < 0) { + printk("CODETEST: fail to enable PCI device\n"); + return -1; + } + /*printk( "CODETEST: found device \"%s\"\n", ct->name ); */ + printk + ("CODETEST: resource \"%s\", start 0x%08x, end 0x%08x, flags 0x%08x\n", + ct->resource[CT_BAR_2].name, + (unsigned int)ct->resource[CT_BAR_2].start, + (unsigned int)ct->resource[CT_BAR_2].end, + (unsigned int)ct->resource[CT_BAR_2].flags); + /* + ** Store the address of the PCI adapter tag port window + */ + ct_phys_addr = ct->resource[CT_BAR_2].start; +#endif + + /* + ** Map the physical addresses of the ports to kernel virtual addresses + */ + printk("CODETEST: attempting to map physical address 0x%08lx\n", + (unsigned long)ct_phys_addr); + ct_ctrl_port_ptr = + (unsigned long *)ioremap_nocache(ct_phys_addr, PAGE_SIZE); + if (ct_ctrl_port_ptr != NULL) { + ct_data_port_ptr = ct_ctrl_port_ptr + 1; + printk + ("CODETEST: physical address 0x%08lx mapped to kernel virtual address 0x%08lx\n", + ct_phys_addr, (unsigned long)ct_ctrl_port_ptr); + } else { + printk + ("CODETEST: ioremap cannot map physical address 0x%08lx to a kernel virtual address\n", + ct_phys_addr); + ct_hooks_enabled = 0; + } + + } + + return 0; +} + +/***************************************************************************/ +int ctTag(unsigned long tagID) +{ + if (ct_ctrl_port_ptr == NULL) + return 0; + + *ct_ctrl_port_ptr = tagID; + return (tagID); + +} /* ctTag */ + +/***************************************************************************/ +int ctDataTag(unsigned long tagID) +{ + if (ct_data_port_ptr == NULL) + return 0; + + *ct_data_port_ptr = tagID; + return (tagID); + +} /* ctDataTag */ + +void ctWriteHWICTaskTags(unsigned n_dtags, const u32 dtags[], u32 tag) +{ + int i = 0; + + /* + ** If enabled, check to see if the tag pointers have been initialized + */ + + if (((ct_hooks_enabled == 0) && (ct_force_hwic_enabled == 0)) || + ((ct_ctrl_port_ptr == NULL) && (ct_init() == -1))) { + return; + } + + while (i < n_dtags) { + *ct_data_port_ptr = dtags[i]; + i++; + } + *ct_ctrl_port_ptr = tag; + + return; +} + +/* +-------------------------------------------------------------------------------| +| +| Accessor functions +| +-------------------------------------------------------------------------------| +*/ + +void ct_enable_pid_task_name(void) +{ + ct_pid_task_name_enabled = 1; +} + +void ct_disable_pid_task_name(void) +{ + ct_pid_task_name_enabled = 0; +} + +void ct_enable_hooks(void) +{ + ct_hooks_enabled = 1; +} + +void ct_disable_hooks(void) +{ + ct_hooks_enabled = 0; +} + +unsigned long ct_get_phys_addr(void) +{ + return ct_phys_addr; +} + +void ct_set_phys_addr(unsigned long addr) +{ + ct_phys_addr = addr; +} + +/* + This function is called to insert a Kernel event tags in the ring buffer + Arguments: n_dtags - number of data tags for this event + dtags - the data tags vector + tag - the control tag for this event +*/ +void ctWriteSWICTaskTags(unsigned n_dtags, const u32 dtags[], u32 tag) +{ + struct Hook_Buffer *hb = ct_hook_buffer; + u32 *pdtags = (u32 *) dtags; + Q_Tag *qp; + /*unsigned long x; */ + + task_tag_count++; /* statistic gathering */ + /* + hb should not be null, but this may be a kernal task + so we are being extra careful + */ + if (hb) { + int n_tags = n_dtags + 1; + /* compute number of empty slots in the ring buffer */ + int slots; + + struct page *ppage; + size_t hb_size = + (sizeof(struct Hook_Buffer) + + PAGE_SIZE) / PAGE_SIZE * PAGE_SIZE; + + spin_lock_irqsave(&hook_buffer_lock, lock_flags); + +#ifdef CT_SWIC_BUFFER_NOCACHE + /* update cache from physical memory */ + for (ppage = virt_to_page((char *)hb); + ppage < virt_to_page((char *)hb + hb_size); ppage++) { + flush_dcache_page(ppage); + } +#endif + + slots = ((hb->head - hb->tail) & (HOOK_BUFFER_SIZE - 1)); + + if (slots == 0) { + slots = HOOK_BUFFER_SIZE - 1; + } else + slots--; + + /* + Disable hardware interrupts while writing tags to the hook buffer. Otherwise, with the + ISR hooks enabled, task and ISR tags could be interleaved. + */ + /*local_irq_save(x); */ + + if (slots < n_tags) { + /* not enough room, flush all but first tag as its + not safe to mess with tag at head */ + int x = hb->head; + while (hb->buffer[x].a_time == HI_BIT_ONLY) { + /* skip over data tags */ + HOOK_INC(x); + } + HOOK_INC(x); /* keep this control tag */ + hb->tail = x; + + /* + Insert a TPP OVERRUN tag to mark the drop of the full buffer + */ + qp = &hb->buffer[hb->tail]; + qp->tag = CT_TPP_OVERRUN_TAG; /* the control tag */ + qp->a_time = ctTagClock() & ~HI_BIT_ONLY; + + HOOK_INC(hb->tail); + + dropped++; /* stats */ + } + + { + while (n_dtags > 0) { + qp = &hb->buffer[hb->tail]; + qp->tag = *pdtags; + qp->a_time = HI_BIT_ONLY; + + HOOK_INC(hb->tail); + pdtags++; + n_dtags--; + } + qp = &hb->buffer[hb->tail]; + qp->tag = tag; /* the control tag */ + qp->a_time = ctTagClock() & ~HI_BIT_ONLY; + + HOOK_INC(hb->tail); + } + /* + Reenable hardware interrupts + */ + /*local_irq_restore(x); */ + +#ifdef CT_SWIC_BUFFER_NOCACHE + /* write cache into physical memory */ + for (ppage = virt_to_page((char *)hb); + ppage < virt_to_page((char *)hb + hb_size); ppage++) { + flush_dcache_page(ppage); + } +#endif + + spin_unlock_irqrestore(&hook_buffer_lock, lock_flags); + + } +} + +/* ------------------------------------------- +int ct_encode_taskname(const char* name, u32 buffer[8]) + + packs name into buffer as required for output as codetest tags. + (TBD, find and reference appropriate doc) + + name is truncated to 32 chars. + + return value is number of words written into buffer[] + + +------------------------------------------------------- */ + +int ct_encode_taskname(const char *name_recv, u32 buffer[8], u32 pid) +{ + size_t len; + int ret; /* return value, number of words written into buffer */ + int index; /* index for buffer [] */ + const char *p; /* walks name backwards in multiples of 4 */ + char pid_string[32]; + int x, i, j; + char name[100]; + + strcpy(name, name_recv); + len = strlen(name); + if (ct_pid_task_name_enabled) { + /*sprintf(pid_string,"%d",pid); + printk("CODETEST: %s\n",pid_string); + strcat(name,pid_string); */ + pid_string[0] = '0'; + for (x = pid, i = 0; x > 0; i++) { + pid_string[i] = (x % 10) + '0'; + x = x / 10; + } + pid_string[i] = '\0'; + //printk("CODETEST: p=%s\n",pid_string); + if (i == 0) + i++; + name[len] = '_'; + len++; + name[len] = '\0'; + for (x = i - 1, j = 0; x >= 0; x--, j++) + name[len + j] = pid_string[x]; + name[len + j] = '\0'; + len = strlen(name); + //printk("CODETEST: n=%s\n",name); + } + if (len > 31) + len = 31; /* truncate if name is too long */ + ret = (len + 3) / 4; + + p = name + (ret - 1) * 4; + + /* The first word is special as it is null padded if + len is not a multiple of 4 */ + + buffer[0] = 0; + switch (len % 4) { + case 0: + p += 4; + ret += 1; + break; + case 3: + buffer[0] += p[2] << 8; + case 2: + buffer[0] += p[1] << 16; + case 1: + buffer[0] += p[0] << 24; + } + p -= 4; + + for (index = 1; index < ret; index++, p -= 4) { + buffer[index] = (p[0] << 24) + (p[1] << 16) + + (p[2] << 8) + p[3]; + } + + return ret; +} + +#if defined(CONFIG_X86) + +static U64 rawClock(void) +{ /* Linux version */ + register U64 result asm("eax"); /* this works, placing upper bits in edx! */ + asm("rdtsc"); /* long long value in edx:eax */ + return result; +} + +/* +Only 31 bits of the clock are used in a CodeTEST tag. +The absolute time to delta time computation in swtpp.c{.w}, +assumes two adjacent tags have absolute times with difference less than +2^31, so it is desirable that the clock not roll over quickly. +Shifting the 64 bit clock by 11, will give a clock rate of +about 2^20 ticks per second on a 2GHz cpu. So, the 31 bit clock will +roll over in 34 minutes. +*/ + +#define CLOCKSHIFT 11 + +u32 ctTagClock(void) +{ + return (rawClock()) >> CLOCKSHIFT; +} + +#elif defined(CONFIG_PPC) + +static u32 rawClock(void) +{ + register unsigned long low asm("%r3"); + register unsigned long high asm("%r4"); + + asm("mftb %r3 "); /* Return value for PPC */ + asm("mftbu %r4"); /* Return upper value for PPC */ + + return low & 0x7fffffff; +} + +u32 ctTagClock(void) +{ + return rawClock(); +} + +#else + +#define MICROS_PER_SECOND 1000000 + +static u32 rawClock(void) +{ + struct timeval tv; + do_gettimeofday(&tv); + return (tv.tv_sec * MICROS_PER_SECOND + tv.tv_usec); +} + +u32 ctTagClock(void) +{ + return rawClock(); +} + +#endif + +/* +-------------------------------------------------------------------------------| +| +| Thread event hooks +| +-------------------------------------------------------------------------------| +*/ + +/* + These functions are called from kernel for task context changes and ISR events +*/ +void ct_thread_create(struct task_struct *p) +{ + u32 count; + u32 tagBuf[9]; + + count = ct_encode_taskname(p->comm, tagBuf, p->pid); + tagBuf[count] = p->pid; + + if (ct_hooks_enabled || ct_force_hwic_enabled) + ctWriteHWICTaskTags(count + 1, tagBuf, + (CT_TASK_CREATE) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); + + if ((ct_hook_buffer != NULL) && (ct_swic_enabled != 0)) + ctWriteSWICTaskTags(count + 1, tagBuf, + (CT_TASK_CREATE) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); +} + +void ct_thread_delete(struct task_struct *p) +{ + u32 count; + u32 tagBuf[9]; + + deleted_thread_id = p->pid; + count = ct_encode_taskname(p->comm, tagBuf, p->pid); + tagBuf[count] = p->pid; + + if (ct_hooks_enabled || ct_force_hwic_enabled) + ctWriteHWICTaskTags(count + 1, tagBuf, + (CT_TASK_DELETE) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); + + if ((ct_hook_buffer != NULL) && (ct_swic_enabled != 0)) + ctWriteSWICTaskTags(count + 1, tagBuf, + (CT_TASK_DELETE) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); +} + +void ct_thread_enter(struct task_struct *next) +{ + u32 count; + u32 tagBuf[9]; + + count = ct_encode_taskname(next->comm, tagBuf, next->pid); + tagBuf[count] = next->pid; + + if (ct_hooks_enabled || ct_force_hwic_enabled) + ctWriteHWICTaskTags(count + 1, tagBuf, + (CT_TASK_ENTER) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); + + if ((ct_hook_buffer != NULL) && (ct_swic_enabled != 0)) + ctWriteSWICTaskTags(count + 1, tagBuf, + (CT_TASK_ENTER) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); +} + +void ct_thread_exit(struct task_struct *prev) +{ + u32 count; + u32 tagBuf[9]; + + /* + ** If this exit comes after the thread have been deleted ignore this tag + ** This algorithm assumes that after a delete event always comes comes an + ** exit event for the deleted thread + */ + if (prev->pid != deleted_thread_id) { + count = ct_encode_taskname(prev->comm, tagBuf, prev->pid); + tagBuf[count] = prev->pid; + + if (ct_hooks_enabled || ct_force_hwic_enabled) + ctWriteHWICTaskTags(count + 1, tagBuf, + (CT_TASK_EXIT) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); + + if ((ct_hook_buffer != NULL) && (ct_swic_enabled != 0)) + ctWriteSWICTaskTags(count + 1, tagBuf, + (CT_TASK_EXIT) | + (CT_TASK_NAMES) | + ((count - 0x01) & 0xffff)); + } else { + /* ignore the exit event */ + deleted_thread_id = -1; + } +} + +/* +-------------------------------------------------------------------------------| +| +| ISR hooks +| +-------------------------------------------------------------------------------| +*/ +void ct_isr_enter(int irq) +{ + if (irq == 0) + return; + if (ct_hooks_enabled || ct_force_hwic_enabled) { + /* + ** Check to see if the tag pointers have been initialized + */ + /* + ** Initialization call removed because, on some xscale platforms, + ** interrupts start before virtual memory has been initialized. + ** JCG 12/2/02 + ** + if( ct_ctrl_port_ptr == NULL && ct_init() == -1 ) + */ + if (ct_ctrl_port_ptr == NULL) { + return; + } + + *ct_ctrl_port_ptr = CT_ISR_ENTER | (irq & 0xffff); + } + if ((ct_hook_buffer != NULL) && (ct_swic_enabled != 0) + && (ct_filter_events == 0)) { + ctWriteSWICTaskTags(0, NULL, (CT_ISR_ENTER) | (irq & 0xffff)); + } + +} + +void ct_isr_exit(int irq) +{ + if (irq == 0) + return; + + if (ct_hooks_enabled || ct_force_hwic_enabled) { + /* + ** Check to see if the tag pointers have been initialized + */ + /* + ** Initialization call removed because interrupts start before + ** virtual memory has been initialized on some platforms + ** JCG 12/2/02 + ** + if( ct_ctrl_port_ptr == NULL && ct_init() == -1 ) + */ + if (ct_ctrl_port_ptr == NULL) { + return; + } + + *ct_ctrl_port_ptr = CT_ISR_EXIT | (irq & 0xffff); + } + if ((ct_hook_buffer != NULL) && (ct_swic_enabled != 0) + && (ct_filter_events == 0)) { + ctWriteSWICTaskTags(0, NULL, (CT_ISR_EXIT) | (irq & 0xffff)); + } +} diff --git a/kernel/ctswic.h b/kernel/ctswic.h new file mode 100644 index 000000000000..c061b436f4f4 --- /dev/null +++ b/kernel/ctswic.h @@ -0,0 +1,41 @@ +#error "please port this file to linux 2.6.18" +/* +-------------------------------------------------------------------------------| +| +| ctswic.h - Header for CodeTEST SWIC data structures used +| in the Linux kernel +| +| Copyright (c) 2003 - 2005 Freescale Semiconductor, Inc. +| +| This software is licensed under the GPL. It may be redistributed +| and/or modified under the terms of the GNU General Public License as +| published by the Free Software Foundation; either version 2 of the +| License, or (at your option) any later version. +| +| Module version: Revision: 1.8 +| +-------------------------------------------------------------------------------| +*/ + +#ifndef CT_SWIC_H_ +#define CT_SWIC_H_ + +/* define this if you disabled in ctdriver.c */ +#ifdef CONFIG_ARM +#define CT_SWIC_BUFFER_NOCACHE +#endif + +typedef struct Q_Tag { + u32 tag; + u32 a_time; +} Q_Tag; + +#define HOOK_BUFFER_SIZE 2048 /* must be a power of two */ + +struct Hook_Buffer { + int head; + volatile int tail; + Q_Tag buffer[HOOK_BUFFER_SIZE]; +}; + +#endif diff --git a/kernel/exit.c b/kernel/exit.c index 06de6c4e8ca3..8d0517838e20 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -47,6 +47,13 @@ #include <asm/pgtable.h> #include <asm/mmu_context.h> +#ifdef CONFIG_CODETEST +/* + * CodeTEST mods + */ +extern void ct_thread_delete(struct task_struct *p); +#endif /* CONFIG_CODETEST */ + extern void sem_exit (void); extern struct task_struct *child_reaper; @@ -768,6 +775,10 @@ static void exit_notify(struct task_struct *tsk) * jobs, send them a SIGHUP and then a SIGCONT. (POSIX 3.2.2.2) */ +#ifdef CONFIG_CODETEST + ct_thread_delete(current); +#endif /* CONFIG_CODETEST */ + INIT_LIST_HEAD(&ptrace_dead); forget_original_parent(tsk, &ptrace_dead); BUG_ON(!list_empty(&tsk->children)); diff --git a/kernel/fork.c b/kernel/fork.c index 8cdd3e72ba55..ec942c006ba7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -56,6 +56,10 @@ #include <asm/cacheflush.h> #include <asm/tlbflush.h> +#ifdef CONFIG_CODETEST +extern void ct_thread_create(struct task_struct *p); +#endif /* CONFIG_CODETEST */ + /* * Protected counters by write_lock_irq(&tasklist_lock) */ @@ -1390,6 +1394,10 @@ long do_fork(unsigned long clone_flags, else p->state = TASK_STOPPED; +#ifdef CONFIG_CODETEST + ct_thread_create(p); +#endif /* CONFIG_CODETEST */ + if (unlikely (trace)) { current->ptrace_message = nr; ptrace_notify ((trace << 8) | SIGTRAP); diff --git a/kernel/sched.c b/kernel/sched.c index a7aeb71140a6..4488ced2d6e1 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -56,6 +56,16 @@ #include <asm/unistd.h> +#ifdef CONFIG_CODETEST +/* + * CodeTEST mods + */ +extern void ct_thread_enter(struct task_struct *next); +extern void ct_thread_exit(struct task_struct *prev); +extern void ct_isr_enter(int irq); +extern void ct_isr_exit(int irq); +#endif /* CONFIG_CODETEST */ + /* * Convert user-nice values [ -20 ... 0 ... 19 ] * to static priority [ MAX_RT_PRIO..MAX_PRIO-1 ], @@ -1844,6 +1854,10 @@ context_switch(struct rq *rq, struct task_struct *prev, spin_release(&rq->lock.dep_map, 1, _THIS_IP_); #endif +#ifdef CONFIG_CODETEST + ct_thread_enter(next); +#endif /* CONFIG_CODETEST */ + /* Here we just switch the register state and the stack. */ switch_to(prev, next, prev); @@ -3449,6 +3463,9 @@ switch_tasks: sched_info_switch(prev, next); if (likely(prev != next)) { next->timestamp = now; +#ifdef CONFIG_CODETEST + ct_thread_exit(prev); +#endif /* CONFIG_CODETEST */ rq->nr_switches++; rq->curr = next; ++*switch_count; |