Back to the Future: A Retroactive Study of Aspect Code

advertisement
Back to the Future:
A Retroactive Study of Aspect
Evolution in Operating System
Code
Sabine Hauert
Plan
 Introduction
 FreeBSD and it’s evolutions
 Goals
 Case studies




Page Daemon Activation
Prefetching
Disk Quotas
Blocking in Device Drivers
 Summary
 Conclusions and discussion
Introduction
FreeBSD
 What is FreeBSD?
 Free operating system
 x86, amd64 compatible
 Alpha/AXP, IA-64, PC-98 and
UltraSPARC® architectures.
 Derived from BSD, the version of UNIX ®
developed at the University of California,
Berkeley.
Introduction
FreeBSD evolution
V2
212,000 LOC
V3
357,000 LOC
V4
474,000 LOC
Introduction
FreeBSD evolution
V2
212,000 LOC
Device Drivers:
V3
357,000 LOC
V4
474,000 LOC
- 581 new
subdirectories
and files
- 100’000 LOC
Introduction
FreeBSD evolution
V2
212,000 LOC
Page daemon
activation sites:
V3
357,000 LOC
V4
474,000 LOC
- 50% less
Introduction
FreeBSD evolution
V2
212,000 LOC
Blocking in
Device Drivers:
V3
357,000 LOC
V4
474,000 LOC
- 50% more
Introduction
Goals
 Analyze the impact of evolution on an “aspectoriented” implementation of the OS.
 Compare with original version




Localization
Configurability
Redundancy
Modularity
Case Studies
Page Daemon Activation
 Frees physical memory when the number
available pages falls below some threshold. The
daemon imposes overhead for determining which
pages will be replaced and for writing them back
to disk if necessary.
 Speed is important
 Context specific
 Crosscuts operations that consume available pages
Case Studies
Page Daemon Activation: Where can it occur?
usr/src/sys/
Vm/
Vm/
swap_pager.c
swap_pager.c
getpages()
getpages() 1
putpages()
putpages() 3
sync()
sync() 1
io_done()
io_done() 2
vm_fault.c
vm_fault.c
additional_pages()
additional_pages() 11
vm_page.c
vm_page.c
unqueue()
unqueue() 11
35
alloc()
alloc() 5
vm_wait()
vm_wait() 11
vm_await() 1+
Kern/
vfs_bio.c
allocbuf()
aspect page_daemon_wakeup {
pointcut unqueuing_available_pages(vm_page_t m):
execution(void vm_page_unqueue(m))
&& cflow(execution(void vm_page_activate(vm_page_t))
|| execution(void vm_page_wire(vm_page_t))
|| execution(void vm_page_unmanage(vm_page_t))
|| execution(void vm_page_deactivate(vm_page_t, int)));
pointcut allocating_buffers(vm_object_t obj, vm_pindex_t pindex):
execution(vm_page_t vm_page_lookup(obj, pindex))
&& cflow(execution(int allocbuf(struct buf*, int)));
around(vm_page_t m):
unqueuing_available_pages(m) {
int queue = m->queue;
proceed(m);
if (((queue - m->pc) == PQ_CACHE)
&& (pages_available() < vm_page_threshold()))
pagedaemon_wakeup();
}
around(vm_object_t obj, vm_pindex_t pindex):
allocating_buffers(obj, pindex) {
vm_page_t m = proceed(obj, pindex);
if ((m != NULL) && !(m->flags & PG_BUSY)
&& ((m->queue - m->pc) == PQ_CACHE)
&& (pages_available() < vfs_page_threshold()))
pagedaemon_wakeup();
return m;
}
Locality
System
-wide
Context
view
Functionality
Case Studies
Page Daemon Activation: Evolution
 Changes are only made to the aspect
 Delete/add poincuts and advice
 Refactoring of threshold checks
 Adding little helper methods
Case Studies
Prefetching for mapped files
 Prefetching is a heuristic designed to
amortize costs by bringing in additional
pages that may be required in the near
future.
 VM suggests pages for prefetching
 File system decides
 crosscuts virtual memory and file systems,
coordinating high-level allocation and lowlevel de-allocation of prefetched pages.
Case Studies
Prefetching for mapped files: Where can it occur?
usr/src/sys/
Vm/
vm_fault.c
vm_fault() 3
additiona_pages() 1
gnu/ext2fs/
ext2_vnops.c
ext2_getpages() 3
ufs/ufs/
ufs_readwrite.c
4+ffs_getpages() 3
ffs_read() 1
aspect mapped_file_prefetching{
pointcut vm_fault_path(vm_map_t map):
cflow(execution(int vm_fault(map,..)));
pointcut getpages_path(vm_map_t map, vm_object_t obj,
vm_page_t* plist, int n, in fpage):
cflow(execution(int ffs_getpages(obj, plist, n, fpage)
|| execution(int vnode_leaf_pager_getpages(obj, plist,n,fpage)));
before(vm_map_t map, vm_object_t obj, vm_page_t* plist, int n,
int fpage):
execution(int vnode_pager_getpages(obj, plist, n, fpage))
&& vm_fault_path(map)
{ …plan and allocate prefetched pages…}
after(vm_object_t obj, vm_page_t* plist, int n, int fpage, int valid):
execution(valid check_valid(..))
&& getpages_path(obj, plist, n, fpage)
{ …dealloc all prefetched pages…}
after(vm_object_t obj, vm_page_t* plist, int n, int fpage,
struct transfer_args* trans_args):
execution(int calc_range(trans_args))
&& getpages_path(obj, plist, len, fpage)
{ …dealloc non contiguous pages… }
…}
Case Studies
Prefetching for mapped files: evolution
 V2->V3: optimized implementation of
sequential mode prefetching to FFS. Use of the
file system read-path for sequential mode.
 Separation of the aspect in two aspects:
 Normal sequential mode aspect
 Optimized sequential aspect
 V3->V4: remove modifications in V3.
 Taking sequential aspect out of Makefile and
recombining both aspects in the normal mode aspect
VS.
Editing of code within FFS operations for a non-AO
system.
Case Studies
Disk Quota
 Designed to track disk utilization and
enforce limits for all users and groups
 Structure: set of low-level disk space
related operations that are consistently
monitoring/limiting all disk usage
 crosscuts disk-consuming operations from
multiple file systems
Case Studies
Disk Quota: Where can it occur?
usr/src/sys/
ufs/ufs/
vnops.c 7 13 +
inode.c 3
vfs.c 1 +
gnu/ext2fs/
gnu/ext2fs/
vfs.c
vfs.c 44
inode.c
inode.c 22
alloc.c
alloc.c 33
vnops.c 8 +
ufs/ffs/
vfs.c 3
inode.c 3
2
3+
alloc.c 5
balloc.c 1 +
Case Studies
Disk Quota
#ifdef QUOTA
if (mp->mnt_flag & MNT_QUOTA) {
int i;
error = vflush(mp, 0, SKIPSYSTEM|flags);
if (error)
#if QUOTA
return (error);
int i;
for (i = 0; i < MAXQUOTAS; i++) {
#endif ...
if (ump->um_quotas[i] == NULLVP)
#if QUOTA
continue;
if (mp->mnt_flag & MNT_QUOTA) {
quotaoff(p, mp, i);
if ((error = vflush(mp, 0, SKIPSYSTEM|flags))
}
!=0)
}
return (error);
#endif ... }
for (i = 0; i < MAXQUOTAS; i++) {
if (ump->um_quotas[i] == NULLVP)
continue;
quotaoff(p, mp, i);
}
}
#endif ... }
aspect disk_quota {
pointcut flushfiles(register struct mount *mp, int flags, struct
proc *p):
execution(int ffs_flushfiles(mp, flags, p))
|| execution(int ext2_flushfiles(mp, flags, p));
around(register struct mount *mp, int flags, struct proc *p):
flushfiles(mp, flags, p) {
register struct ufsmount *ump;
ump = VFSTOUFS(mp);
if (mp->mnt_flag & MNT_QUOTA) {
int i;
int error = vflush(mp, NULLVP, SKIPSYSTEM|flags);
if (error)
return (error);
for (i = 0; i < MAXQUOTAS; i++) {
if (ump->um_quotas[i] == NULLVP)
continue;
quotaoff(p, mp, i);
}
}
return proceed(mp, flags, p);
}
Case Studies
Disk Quota: Evolution
 Adding pointcuts and advice is needed to
incrementally extend its configuration to
include new functionality.
 V2->V3: new feature for server which
automatically assigned the ownership of a new
file to be that of the enclosing directory.
Case Studies
Blocking in device drivers
 Explicitly surrender the CPU and block,
allowing another process to run
 Keep CPU busy while processes waits for
device I/O
 crosscuts all device-specific operations
involved with I/O
Case Studies
Blocking: Where can it occur?
version
LOC
devices
(subdirs)
Calls to
tsleep()
Tsleep() w/
no timeout
2
8400
7
5
2
3
46900
27
55
11
4
114800
69
110
22
Case Studies
Blocking: tracking non-timeout tsleeps()
aspect device_blocked_notimeout {
pointcut block_in_device(void* ident, int priority, const char* wmesg, int timo):
call(int tsleep(ident, priority, wmesg, timo))
&& within(“/usr/src/sys/dev”);
before(void* ident, int priority, const char* wmesg, int timo):
block_in_device(ident, priority, wmesg, timo) {
if (timo == 0)
printf(“Blocking in device, no timeout:
%s pid: %d\n”, wmesg, curproc->p_pid); }
}
Case Studies
Disk Quota: Evolution
 No evolution needed!
concern
Major evolution
Page daemon
wakeup
Structural
challenge
Original/aspect
Benefits
Revamping of
Multiple context
code it
specific
crosscuts: VM
thresholds
and buffer cache
Scattered
activation
/
Textually
localized
Independent
development &
localized
change
Prefetching for
mapped files
Change in
design of
sequential mode
New subsystem
interaction
along execution
paths
Internal to
function
/
Explicit control
flow
Explicit
subsystem
interaction &
pluggability in
makefile
Disk quota
New
functionality in
code it
crosscuts:
UFS,FFS,EXT2
Configurability
And sharing
across file
systems
#ifdefs w/
redundant code
/
Explicit sharing
Pointcut
configurability
& reduced
redundancy
Device blocking
New device
drivers added to
the system
Consistency
across rapidly
growing
diversity
Individualized
devices /
Centralized
assessment
Comprehensive
coverage &
further
extensibility
modularized
Conclusion
 Changeability
 Textual locality => consistency
 Configurability
 Modifying aspects
 Modifying makefile options
 Redundancy
 Quota aspect example
 Extensibility
 Device aspect
Discussion
 What about the disadvantages?
 How biased is the analysis?
 How to define the limit between what
should be in an aspect and what shouldn’t:
core functionality vs. non core functionality.
 Can we know how a system will evolve?
Download