Back to the Future: A Retroactive Study of Aspect Evolution
28 Slides359.50 KB
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 ffs getpages() 4 3ffs 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 713 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 Structural challenge Original/aspect Benefits Page daemon wakeup Revamping of code it crosscuts: VM and buffer cache Multiple context specific thresholds 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?