Building systems with aspects from ground up: a practitioners account

advertisement
AspeCt-oriented C (ACC)
Hans-Arno Jacobsen
ECE 297
Aspects in ACC

An aspect is a file with .acc extension with C code
helper
function
named pointcut
before any
function call,
increase the
counter
after executing
main, print result
#include <stdio.h>
counter
int functionCounter;
void printResult() {
printf(“total functions called = %d\n”, functionCounter;
}
pointcut ExecMain(): execution (int main()) ;
before(): ExecMain() {
before executing
functionCounter = 0;
main, initialize counter
}
before() : call($ $(…)) {
functionCounter ++;
}
after(): ExecMain() {
Aspect counting # of
printResult();
function calls
}
© 2009 Hans-Arno Jacobsen
2
Memory Profiling Aspect
#include <stdio.h>
#include <stdlib.h>
size_t totalMem = 0;
void print() {
printf("total = %d \n", totalMem);
}
advice
after(): execution(int main()) {
print();
}
pointcut
before(size_t s): call($ malloc(...)) && args(s) {
totalMem += s;
}
© 2009 Hans-Arno Jacobsen
3
Platform Support
…
#ifdef __MIPSEB__
/* For big-endian machines. */
#define va_arg(__AP, __type)
\
((__AP = (char *) ((__alignof__ (__type) > 4
\
? ((int)__AP + 8 - 1) & -8
\
: ((int)__AP + 4 - 1) & -4)
\
+ __va_rounded_size (__type))),
\
*(__type *) (void *) (__AP - __va_rounded_size (__type)))
#else
/* For little-endian machines. */
…
• More of the above
#endif
• Hardware platform specific
#endif
customizations
#endif /* ! defined (__mips_eabi) */
OS/161 Kernel:
kern/arch/mips/include/stdarg.h
© 2009 Hans-Arno Jacobsen
7
Error Checking Concern
• Error checking code
scatters across code base
static int __init readonly(char *str) {
• It cuts across core logic
if (*str)
return 0;
root_mountflags |= MS_RDONLY;
return 1;
}
static int __init readwrite(char *str) {
if (*str)
return 0;
root_mountflags &= ~MS_RDONLY;
return 1;
}
© 2009 Hans-Arno Jacobsen
Linux Kernel 2.6: kernel initialization: do_mount.c
…
8
Multiprocessor Support I
static int
try_to_wake_up(task_t *p, unsigned int state, int sync) {
int cpu, this_cpu, success = 0;
unsigned long flags;
long old_state;
runqueue_t *rq;
#ifdef CONFIG_SMP
unsigned long load, this_load;
struct sched_domain *sd, *this_sd = NULL;
int new_cpu;
#endif
… (next slide)
© 2009 Hans-Arno Jacobsen
Linux Kernel 2.6: kernel/sched.c
9
Multiprocessor Support II
rq = task_rq_lock(p, &flags);
old_state = p->state;
if (!(old_state & state)) • pieces of multiprocessing concern
tangled with core logic (1 CPU
goto out;
case)
if (p->array)
goto out_running; • not the same piece of code as in
previous cases
cpu = task_cpu(p);
this_cpu = smp_processor_id();
#ifdef CONFIG_SMP
if (unlikely(task_running(rq, p)))
goto out_activate;
new_cpu = cpu;
schedstat_inc(rq, ttwu_cnt);
…
#endif
© 2009 Hans-Arno Jacobsen
10
Summary




Certain concerns crosscut the principal or core logic
(a.k.a. crosscutting concerns)
Similar concern code scatters across the code base
Different pieces of concern code tangled with core
logic
Scattering, tangling, and crosscutting apparently leads
to code




that is hard to read and understand, let alone maintain
where the design intent is not cleanly represented in the code
where concerns are not well separated and modularized
removing a concern is error-prone
© 2009 Hans-Arno Jacobsen
11
Crosscutting in C
void *NutHeapAlloc(size_t size) {
#ifdef NUTDEBUG
//code removed
#endif
NODE **fpp = 0;
//code removed
#if defined(__arm__) ||
defined(__m68k__) ||
defined(__H8300H__) || …
while ((size & 0x03) != 0)
size++;
#endif
if (size >= available) {
#ifdef NUTDEBUG
//code removed
#endif
return 0;
}
//code removed
…(next column)
while (node) {
Nut/OS, heap.c
//code removed
if (fit) {
//split the node if too big
if (fit->hn_size > …) {
//code removed
*fpp = node;
} else
*fpp = fit->hn_next;
…}
//code removed
debug concern
}
system-specific concern
#ifdef NUTDEBUG
//code removed
optimization concern
#endif
main functionality
return fit; }
© 2009 Hans-Arno Jacobsen
12
Another Way to Visualize Crosscutting
A file (a module)




Red shows lines pertaining to the given concern
Not in just one place (i.e., file, function)
Not even in a small number of places (files or functions)
Most code would show very similar footprints
Is there a Solution?
For separating crosscutting concerns from core
code
 Pick and choose the concerns required (based
on hardware platform etc.)

© 2009 Hans-Arno Jacobsen
14
Yes  !
© 2009 Hans-Arno Jacobsen
15
AOP Key Idea
base/core program
weaver
final system
aspect
© 2009 Hans-Arno Jacobsen
16
Aspect-oriented Programming





AOP is

a programming paradigm that aims to support the
modularization of crosscutting concerns in software

complementary to existing paradigms
Emerged about 10 years ago from different research
efforts studying the separation of concerns in
software
Supported in industry today by IBM, BEA,…
AOP support is available for Java, C++, C, PHP, …
AspectJ, AspectC++, AspectC, AOPHP, …
© 2009 Hans-Arno Jacobsen
17
AspeCt-oriented C (ACC)

Designed by Michael Gong and Hans-Arno Jacobsen




started around April 2006
as an effort by the Middleware Systems Research Group at the
University of Toronto
An aspect-oriented extension to C
Highlights comprise







ANSI-C and C99 compliance
gcc source-compatibility
Compiler and generated code portability
Seamless Linux, Mac OSX, Solaris and Windows support
Integration into existing build processes possible
Code transparency through source-to-source transformations
Open source license for ACC compiler
© 2009 Hans-Arno Jacobsen
18
ACC Key Idea
normal C files
ACC
compilation
compilation
normal C files
executable
C files with ACC extensions
© 2009 Hans-Arno Jacobsen
20
Example: ACC Key Idea
Join point declaration
Pointcut
before(): call ( $ $bootstrap$(...) )
declaration
{
printf("> Entering %s \n", this->funcName);
}
advice
© 2009 Hans-Arno Jacobsen
21
Join Points

Well-defined points in the execution of a program



Examples for C




The point a function is called
The point a function is executed
Function calls
(before/after)
Function execution (before/after)
…
(call site)
(called site)
Examples for Java




Method calls & execution
Field reads & writes
Exceptions
…
© 2009 Hans-Arno Jacobsen
22
Pointcuts




Declaratively define sets of join points
Call pointcut (all join points associated with the call
of a function)
Execution pointcut (all join points associated with
the execution of a function)
Example
call($ $bootstrap$(...))



All call join points involving functions that contain the
word “bootstrap” in the function name
With any list of input parameter types
With any return value type
© 2009 Hans-Arno Jacobsen
23
Advice

The code executed when the associated
pointcut matches a join point
© 2009 Hans-Arno Jacobsen
24
Building Software Product Lines

16 instances of RBT
core
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
rb-test.c
test.c
rb.c
ACC
thread pointer
trace
node count
memory profiler
aspects
© 2009 Hans-Arno Jacobsen
16
28
Use of AOP in Practice
Design aspects into systems right from the
start (i.e., design with aspects in mind)
 Use aspects to aid in debugging, analyzing,
profiling
 Development of software product lines
 Use aspects to refactor existing systems

Tailoring and customization
 Adaptation
 Extension

© 2009 Hans-Arno Jacobsen
29
AspeCtC Resources

http://www.AspeCtC.net

AspeCtC Tutorial on the web site

AspeCtC Language Specification

See the AspeCtC web site for submitting a bug
report, if you think you found one
© 2009 Hans-Arno Jacobsen
30
Other Resources on AOP

Aspect-oriented Software Development Portal


AspectJ


http://www.eclipse.org/aspectj/
AspectC++


http://www.aosd.net
http://www.aspectc.org
AspeCtC

http://www.AspeCtC.net
© 2009 Hans-Arno Jacobsen
31
© 2009 Hans-Arno Jacobsen
32
ACC Work Flow
© 2009 Hans-Arno Jacobsen
33
ACC Features












join point: function call/execution, variable set/get
advice: before, after , and around
pointcut:call(), execution(), args(), infile(), infunc(), result()
pointcut composition, named pointcut
proceed() , cflow(), preturn()
wildcard character matching through “$” and “…”
exception handling:
 try() pointcut, catch() advice, throw() call
reflective information about join points
static crosscutting support : add new struct/union member
 intype() pointcut and introduce() advice
support debugging on the original sources
match join points inside aspects
seemingly integration into existing building system: tacc
© 2009 Hans-Arno Jacobsen
34
ACC Example: Nut/OS

Ethernut project


hardware and open source software project for
building tiny embedded Ethernet devices.
hardware





http://www.ethernut.de/en/
ATmega128 CPU
on-chip 128 kBytes of Flash memory
external 32 kByte SRAM
10 MBit Ethernet interface
software

Nut/OS
 a simple real-time-operating-system

~110 KLOC
© 2009 Hans-Arno Jacobsen
35
ACC Example: Tracing In Nut/OS
© 2009 Hans-Arno Jacobsen
36
ACC Example: GCC

Aspectized GCC 4

a tracing aspect for GCC
GCC internal function calls during compilation:
#include<stdio.h>
void main(){
char *cool = "cool";
printf("%s\n",cool);
}
1. main
2. xmalloc_set_program_name
3. unlock_std_streams
4. unlock_1
5. unlock_1
…
637925: delete_temp_files
637926: delete_if_ordinary
637927: stat
637928: delete_if_ordinary
637929: stat
© 2009 Hans-Arno Jacobsen
37
www.
aspectc
© 2009 Hans-Arno Jacobsen
.net
38
© 2009 Hans-Arno Jacobsen
39
Example: Memory Profiling I
size_t totalMemoryAllocated;
int totalAllocationFuncCalled;
int totalFreeFuncCalled;
void initProfiler(){
totalMemoryAllocated = 0;
totalAllocationFuncCalled = 0;
totalFreeFuncCalled = 0;
}
void printProfiler(){
printf("total memory allocated = %d bytes\n",
totalMemoryAllocated);
…
totalAllocationFuncCalled);
…
totalFreeFuncCalled);
}
© 2009 Hans-Arno Jacobsen
40
Example: Memory Profiling II
before(): execution(int main()) {
initProfiler();
}
after(): execution(int main()) {
printProfiler();
}
before(size_t s): call($ malloc(...)) && args(s) {
totalMemoryAllocated += s;
totalAllocationFuncCalled ++;
}
© 2009 Hans-Arno Jacobsen
41
Example: Memory Profiling III
before(size_t n, size_t s): call($ calloc(...)) && args(n, s) {
totalMemoryAllocated += n * s;
totalAllocationFuncCalled ++;
}
before(size_t s): call($ realloc(...)) && args(void *, s) {
totalMemoryAllocated += s;
totalAllocationFuncCalled ++;
}
before() : call(void free(void *)) {
totalFreeFuncCalled++;
}
© 2009 Hans-Arno Jacobsen
42
Example: Memory Profiling IV

Is the code thread safe?

Is thread-safety an aspect?

Left as an exercise for the reader .
© 2009 Hans-Arno Jacobsen
43
Download