Changes in / [1f7753a:a7f7ed12] in mainline
- Files:
-
- 2 deleted
- 22 edited
-
abi/include/mm/as.h (modified) (1 diff)
-
boot/arch/ia64/src/main.c (modified) (1 diff)
-
contrib/conf/ski.conf (modified) (1 diff)
-
kernel/arch/ia64/include/mm/as.h (modified) (1 diff)
-
kernel/arch/ia64/src/mm/tlb.c (modified) (4 diffs)
-
kernel/genarch/src/mm/page_ht.c (modified) (1 diff)
-
kernel/genarch/src/mm/page_pt.c (modified) (6 diffs)
-
kernel/generic/include/config.h (modified) (1 diff)
-
kernel/generic/include/mm/as.h (modified) (2 diffs)
-
kernel/generic/include/proc/task.h (modified) (1 diff)
-
kernel/generic/src/interrupt/interrupt.c (modified) (1 diff)
-
kernel/generic/src/main/kinit.c (modified) (1 diff)
-
kernel/generic/src/mm/as.c (modified) (3 diffs)
-
kernel/generic/src/mm/backend_anon.c (modified) (8 diffs)
-
kernel/generic/src/mm/backend_elf.c (modified) (3 diffs)
-
kernel/generic/src/mm/backend_phys.c (modified) (3 diffs)
-
kernel/generic/src/mm/km.c (modified) (3 diffs)
-
kernel/generic/src/proc/program.c (modified) (2 diffs)
-
kernel/generic/src/proc/task.c (modified) (1 diff)
-
uspace/lib/c/Makefile (modified) (1 diff)
-
uspace/lib/c/generic/fibril.c (modified) (6 diffs)
-
uspace/lib/c/generic/stack.c (deleted)
-
uspace/lib/c/generic/thread.c (modified) (3 diffs)
-
uspace/lib/c/include/stack.h (deleted)
Legend:
- Unmodified
- Added
- Removed
-
abi/include/mm/as.h
r1f7753a ra7f7ed12 37 37 38 38 /** Address space area flags. */ 39 #define AS_AREA_READ 0x01 40 #define AS_AREA_WRITE 0x02 41 #define AS_AREA_EXEC 0x04 42 #define AS_AREA_CACHEABLE 0x08 43 #define AS_AREA_GUARD 0x10 44 #define AS_AREA_LATE_RESERVE 0x20 39 #define AS_AREA_READ 0x01 40 #define AS_AREA_WRITE 0x02 41 #define AS_AREA_EXEC 0x04 42 #define AS_AREA_CACHEABLE 0x08 43 #define AS_AREA_GUARD 0x10 45 44 46 45 /** Address space area info exported to uspace. */ -
boot/arch/ia64/src/main.c
r1f7753a ra7f7ed12 48 48 49 49 #define DEFAULT_MEMORY_BASE 0x4000000ULL 50 #define DEFAULT_MEMORY_SIZE (256 * 1024 * 1024)50 #define DEFAULT_MEMORY_SIZE 0x4000000ULL 51 51 #define DEFAULT_LEGACY_IO_BASE 0x00000FFFFC000000ULL 52 52 #define DEFAULT_LEGACY_IO_SIZE 0x4000000ULL -
contrib/conf/ski.conf
r1f7753a ra7f7ed12 1 load image.boot1 load HelenOS/image.boot -
kernel/arch/ia64/include/mm/as.h
r1f7753a ra7f7ed12 43 43 #define USER_ADDRESS_SPACE_END_ARCH UINT64_C(0xdfffffffffffffff) 44 44 45 #define USTACK_ADDRESS_ARCH UINT64_C(0x0000000ff0000000) 46 45 47 typedef struct { 46 48 } as_arch_t; -
kernel/arch/ia64/src/mm/tlb.c
r1f7753a ra7f7ed12 113 113 va = page; 114 114 115 rr.word = rr_read(VA2VRN( page));116 if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN( page))))) {115 rr.word = rr_read(VA2VRN(va)); 116 if ((restore_rr = (rr.map.rid != ASID2RID(asid, VA2VRN(va))))) { 117 117 /* 118 118 * The selected region register does not contain required RID. … … 122 122 123 123 rr0 = rr; 124 rr0.map.rid = ASID2RID(asid, VA2VRN( page));125 rr_write(VA2VRN( page), rr0.word);124 rr0.map.rid = ASID2RID(asid, VA2VRN(va)); 125 rr_write(VA2VRN(va), rr0.word); 126 126 srlz_d(); 127 127 srlz_i(); … … 139 139 case 1: /* cnt 4 - 15 */ 140 140 ps = PAGE_WIDTH + 2; 141 va &= ~((1 UL<< ps) - 1);141 va &= ~((1 << ps) - 1); 142 142 break; 143 143 case 2: /* cnt 16 - 63 */ 144 144 ps = PAGE_WIDTH + 4; 145 va &= ~((1 UL<< ps) - 1);145 va &= ~((1 << ps) - 1); 146 146 break; 147 147 case 3: /* cnt 64 - 255 */ 148 148 ps = PAGE_WIDTH + 6; 149 va &= ~((1 UL<< ps) - 1);149 va &= ~((1 << ps) - 1); 150 150 break; 151 151 case 4: /* cnt 256 - 1023 */ 152 152 ps = PAGE_WIDTH + 8; 153 va &= ~((1 UL<< ps) - 1);153 va &= ~((1 << ps) - 1); 154 154 break; 155 155 case 5: /* cnt 1024 - 4095 */ 156 156 ps = PAGE_WIDTH + 10; 157 va &= ~((1 UL<< ps) - 1);157 va &= ~((1 << ps) - 1); 158 158 break; 159 159 case 6: /* cnt 4096 - 16383 */ 160 160 ps = PAGE_WIDTH + 12; 161 va &= ~((1 UL<< ps) - 1);161 va &= ~((1 << ps) - 1); 162 162 break; 163 163 case 7: /* cnt 16384 - 65535 */ 164 164 case 8: /* cnt 65536 - (256K - 1) */ 165 165 ps = PAGE_WIDTH + 14; 166 va &= ~((1 UL<< ps) - 1);166 va &= ~((1 << ps) - 1); 167 167 break; 168 168 default: 169 169 ps = PAGE_WIDTH + 18; 170 va &= ~((1 UL<< ps) - 1);170 va &= ~((1 << ps) - 1); 171 171 break; 172 172 } 173 173 174 for (; va < (page + cnt * PAGE_SIZE); va += (1 UL<< ps))174 for (; va < (page + cnt * PAGE_SIZE); va += (1 << ps)) 175 175 asm volatile ( 176 176 "ptc.l %[va], %[ps] ;;" … … 183 183 184 184 if (restore_rr) { 185 rr_write(VA2VRN( page), rr.word);185 rr_write(VA2VRN(va), rr.word); 186 186 srlz_d(); 187 187 srlz_i(); -
kernel/genarch/src/mm/page_ht.c
r1f7753a ra7f7ed12 209 209 pte->frame = ALIGN_DOWN(frame, FRAME_SIZE); 210 210 211 /*212 * Make sure that a concurrent ht_mapping_find() will see the213 * new entry only after it is fully initialized.214 */215 211 write_barrier(); 216 212 -
kernel/genarch/src/mm/page_pt.c
r1f7753a ra7f7ed12 89 89 PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | 90 90 PAGE_WRITE); 91 /*92 * Make sure that a concurrent hardware page table walk or93 * pt_mapping_find() will see the new PTL1 only after it is94 * fully initialized.95 */96 91 write_barrier(); 97 92 SET_PTL1_PRESENT(ptl0, PTL0_INDEX(page)); … … 108 103 PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | 109 104 PAGE_WRITE); 110 /*111 * Make the new PTL2 visible only after it is fully initialized.112 */113 105 write_barrier(); 114 106 SET_PTL2_PRESENT(ptl1, PTL1_INDEX(page)); … … 125 117 PAGE_NOT_PRESENT | PAGE_USER | PAGE_EXEC | PAGE_CACHEABLE | 126 118 PAGE_WRITE); 127 /*128 * Make the new PTL3 visible only after it is fully initialized.129 */130 119 write_barrier(); 131 120 SET_PTL3_PRESENT(ptl2, PTL2_INDEX(page)); … … 136 125 SET_FRAME_ADDRESS(ptl3, PTL3_INDEX(page), frame); 137 126 SET_FRAME_FLAGS(ptl3, PTL3_INDEX(page), flags | PAGE_NOT_PRESENT); 138 /*139 * Make the new mapping visible only after it is fully initialized.140 */141 127 write_barrier(); 142 128 SET_FRAME_PRESENT(ptl3, PTL3_INDEX(page)); … … 310 296 311 297 #if (PTL1_ENTRIES != 0) 312 /*313 * Always read ptl2 only after we are sure it is present.314 */315 298 read_barrier(); 316 299 #endif … … 321 304 322 305 #if (PTL2_ENTRIES != 0) 323 /*324 * Always read ptl3 only after we are sure it is present.325 */326 306 read_barrier(); 327 307 #endif -
kernel/generic/include/config.h
r1f7753a ra7f7ed12 44 44 #define STACK_FRAMES TWO_FRAMES 45 45 #define STACK_SIZE ((1 << STACK_FRAMES) << PAGE_WIDTH) 46 47 #define STACK_SIZE_USER (1 * 1024 * 1024)48 46 49 47 #define CONFIG_INIT_TASKS 32 -
kernel/generic/include/mm/as.h
r1f7753a ra7f7ed12 61 61 #define USER_ADDRESS_SPACE_END USER_ADDRESS_SPACE_END_ARCH 62 62 63 #ifdef USTACK_ADDRESS_ARCH 64 #define USTACK_ADDRESS USTACK_ADDRESS_ARCH 65 #else 66 #define USTACK_ADDRESS (USER_ADDRESS_SPACE_END - (STACK_SIZE - 1)) 67 #endif 68 63 69 /** Kernel address space. */ 64 70 #define FLAG_AS_KERNEL (1 << 0) … … 218 224 void (* destroy)(as_area_t *); 219 225 220 bool (* is_resizable)(as_area_t *);221 bool (* is_shareable)(as_area_t *);222 223 226 int (* page_fault)(as_area_t *, uintptr_t, pf_access_t); 224 227 void (* frame_free)(as_area_t *, uintptr_t, uintptr_t); -
kernel/generic/include/proc/task.h
r1f7753a ra7f7ed12 134 134 uint64_t ucycles; 135 135 uint64_t kcycles; 136 137 /** If true, do not attempt to print a verbose kill message. */138 bool silent_kill;139 136 } task_t; 140 137 -
kernel/generic/src/interrupt/interrupt.c
r1f7753a ra7f7ed12 168 168 static NO_TRACE void fault_from_uspace_core(istate_t *istate, const char *fmt, va_list args) 169 169 { 170 if (!TASK->silent_kill) { 171 printf("Task %s (%" PRIu64 ") killed due to an exception at " 172 "program counter %p.\n", TASK->name, TASK->taskid, 173 (void *) istate_get_pc(istate)); 174 175 istate_decode(istate); 176 stack_trace_istate(istate); 177 178 printf("Kill message: "); 179 vprintf(fmt, args); 180 printf("\n"); 181 } 170 printf("Task %s (%" PRIu64 ") killed due to an exception at " 171 "program counter %p.\n", TASK->name, TASK->taskid, 172 (void *) istate_get_pc(istate)); 173 174 istate_decode(istate); 175 stack_trace_istate(istate); 176 177 printf("Kill message: "); 178 vprintf(fmt, args); 179 printf("\n"); 182 180 183 181 task_kill_self(true); -
kernel/generic/src/main/kinit.c
r1f7753a ra7f7ed12 172 172 #endif /* CONFIG_KCONSOLE */ 173 173 174 /*175 * Store the default stack size in sysinfo so that uspace can create176 * stack with this default size.177 */178 sysinfo_set_item_val("default.stack_size", NULL, STACK_SIZE_USER);179 180 174 interrupts_enable(); 181 175 -
kernel/generic/src/mm/as.c
r1f7753a ra7f7ed12 426 426 /* 427 427 * So far, the area does not conflict with other areas. 428 * Check if it is contained in the useraddress space.428 * Check if it doesn't conflict with kernel address space. 429 429 */ 430 430 if (!KERNEL_ADDRESS_SPACE_SHADOWED) { 431 return iswithin(USER_ADDRESS_SPACE_START, 432 (USER_ADDRESS_SPACE_END - USER_ADDRESS_SPACE_START) + 1, 433 addr, P2SZ(count)); 431 return !overlaps(addr, P2SZ(count), KERNEL_ADDRESS_SPACE_START, 432 KERNEL_ADDRESS_SPACE_END - KERNEL_ADDRESS_SPACE_START); 434 433 } 435 434 … … 697 696 return ENOENT; 698 697 } 699 700 if (!area->backend->is_resizable(area)) { 701 /* 702 * The backend does not support resizing for this area. 698 699 if (area->backend == &phys_backend) { 700 /* 701 * Remapping of address space areas associated 702 * with memory mapped devices is not supported. 703 703 */ 704 704 mutex_unlock(&area->lock); … … 1057 1057 } 1058 1058 1059 if (!src_area->backend->is_shareable(src_area)) { 1060 /* 1061 * The backend does not permit sharing of this area. 1059 if ((!src_area->backend) || (!src_area->backend->share)) { 1060 /* 1061 * There is no backend or the backend does not 1062 * know how to share the area. 1062 1063 */ 1063 1064 mutex_unlock(&src_area->lock); -
kernel/generic/src/mm/backend_anon.c
r1f7753a ra7f7ed12 59 59 static void anon_destroy(as_area_t *); 60 60 61 static bool anon_is_resizable(as_area_t *);62 static bool anon_is_shareable(as_area_t *);63 64 61 static int anon_page_fault(as_area_t *, uintptr_t, pf_access_t); 65 62 static void anon_frame_free(as_area_t *, uintptr_t, uintptr_t); … … 71 68 .destroy = anon_destroy, 72 69 73 .is_resizable = anon_is_resizable,74 .is_shareable = anon_is_shareable,75 76 70 .page_fault = anon_page_fault, 77 71 .frame_free = anon_frame_free, … … 80 74 bool anon_create(as_area_t *area) 81 75 { 82 if (area->flags & AS_AREA_LATE_RESERVE)83 return true;84 85 76 return reserve_try_alloc(area->pages); 86 77 } … … 88 79 bool anon_resize(as_area_t *area, size_t new_pages) 89 80 { 90 if (area->flags & AS_AREA_LATE_RESERVE)91 return true;92 93 81 if (new_pages > area->pages) 94 82 return reserve_try_alloc(new_pages - area->pages); … … 112 100 ASSERT(mutex_locked(&area->as->lock)); 113 101 ASSERT(mutex_locked(&area->lock)); 114 ASSERT(!(area->flags & AS_AREA_LATE_RESERVE));115 102 116 103 /* … … 152 139 void anon_destroy(as_area_t *area) 153 140 { 154 if (area->flags & AS_AREA_LATE_RESERVE)155 return;156 157 141 reserve_free(area->pages); 158 142 } 159 143 160 bool anon_is_resizable(as_area_t *area)161 {162 return true;163 }164 165 bool anon_is_shareable(as_area_t *area)166 {167 return !(area->flags & AS_AREA_LATE_RESERVE);168 }169 144 170 145 /** Service a page fault in the anonymous memory address space area. … … 250 225 * the different causes 251 226 */ 252 253 if (area->flags & AS_AREA_LATE_RESERVE) {254 /*255 * Reserve the memory for this page now.256 */257 if (!reserve_try_alloc(1)) {258 printf("Killing task %" PRIu64 " due to a "259 "failed late reservation request.\n",260 TASK->taskid);261 TASK->silent_kill = true;262 return AS_PF_FAULT;263 }264 }265 266 227 kpage = km_temporary_page_get(&frame, FRAME_NO_RESERVE); 267 228 memsetb((void *) kpage, PAGE_SIZE, 0); … … 294 255 ASSERT(mutex_locked(&area->lock)); 295 256 296 if (area->flags & AS_AREA_LATE_RESERVE) { 297 /* 298 * In case of the late reserve areas, physical memory will not 299 * be unreserved when the area is destroyed so we need to use 300 * the normal unreserving frame_free(). 301 */ 302 frame_free(frame); 303 } else { 304 /* 305 * The reserve will be given back when the area is destroyed or 306 * resized, so use the frame_free_noreserve() which does not 307 * manipulate the reserve or it would be given back twice. 308 */ 309 frame_free_noreserve(frame); 310 } 257 frame_free_noreserve(frame); 311 258 } 312 259 -
kernel/generic/src/mm/backend_elf.c
r1f7753a ra7f7ed12 58 58 static void elf_destroy(as_area_t *); 59 59 60 static bool elf_is_resizable(as_area_t *);61 static bool elf_is_shareable(as_area_t *);62 63 60 static int elf_page_fault(as_area_t *, uintptr_t, pf_access_t); 64 61 static void elf_frame_free(as_area_t *, uintptr_t, uintptr_t); … … 69 66 .share = elf_share, 70 67 .destroy = elf_destroy, 71 72 .is_resizable = elf_is_resizable,73 .is_shareable = elf_is_shareable,74 68 75 69 .page_fault = elf_page_fault, … … 219 213 } 220 214 221 bool elf_is_resizable(as_area_t *area)222 {223 return true;224 }225 226 bool elf_is_shareable(as_area_t *area)227 {228 return true;229 }230 231 232 215 /** Service a page fault in the ELF backend address space area. 233 216 * -
kernel/generic/src/mm/backend_phys.c
r1f7753a ra7f7ed12 52 52 static void phys_destroy(as_area_t *); 53 53 54 static bool phys_is_resizable(as_area_t *);55 static bool phys_is_shareable(as_area_t *);56 57 58 54 static int phys_page_fault(as_area_t *, uintptr_t, pf_access_t); 59 55 … … 63 59 .share = phys_share, 64 60 .destroy = phys_destroy, 65 66 .is_resizable = phys_is_resizable,67 .is_shareable = phys_is_shareable,68 61 69 62 .page_fault = phys_page_fault, … … 94 87 /* Nothing to do. */ 95 88 } 96 97 bool phys_is_resizable(as_area_t *area)98 {99 return false;100 }101 102 bool phys_is_shareable(as_area_t *area)103 {104 return true;105 }106 107 89 108 90 /** Service a page fault in the address space area backed by physical memory. -
kernel/generic/src/mm/km.c
r1f7753a ra7f7ed12 233 233 * @param[inout] framep Pointer to a variable which will receive the physical 234 234 * address of the allocated frame. 235 * @param[in] flags Frame allocation flags. FRAME_NONE, FRAME_NO_RESERVE 236 * and FRAME_ATOMIC bits are allowed. 235 * @param[in] flags Frame allocation flags. FRAME_NONE or FRAME_NO_RESERVE. 237 236 * @return Virtual address of the allocated frame. 238 237 */ … … 244 243 ASSERT(THREAD); 245 244 ASSERT(framep); 246 ASSERT(!(flags & ~ (FRAME_NO_RESERVE | FRAME_ATOMIC)));245 ASSERT(!(flags & ~FRAME_NO_RESERVE)); 247 246 248 247 /* … … 256 255 ASSERT(page); // FIXME 257 256 } else { 258 frame = (uintptr_t) frame_alloc(ONE_FRAME, 259 FRAME_LOWMEM | flags); 260 if (!frame) 261 return (uintptr_t) NULL; 257 frame = (uintptr_t) frame_alloc_noreserve(ONE_FRAME, 258 FRAME_LOWMEM); 262 259 page = PA2KA(frame); 263 260 } -
kernel/generic/src/proc/program.c
r1f7753a ra7f7ed12 79 79 * Create the stack address space area. 80 80 */ 81 uintptr_t virt = (uintptr_t) -1; 82 uintptr_t bound = USER_ADDRESS_SPACE_END - (STACK_SIZE_USER - 1); 83 84 /* Adjust bound to create space for the desired guard page. */ 85 bound -= PAGE_SIZE; 86 81 uintptr_t virt = USTACK_ADDRESS; 87 82 as_area_t *area = as_area_create(as, 88 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD | 89 AS_AREA_LATE_RESERVE, STACK_SIZE_USER, AS_AREA_ATTR_NONE, 90 &anon_backend, NULL, &virt, bound); 83 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE, 84 STACK_SIZE, AS_AREA_ATTR_NONE, &anon_backend, NULL, &virt, 0); 91 85 if (!area) { 92 86 task_destroy(prg->task); … … 99 93 kernel_uarg->uspace_entry = (void *) entry_addr; 100 94 kernel_uarg->uspace_stack = (void *) virt; 101 kernel_uarg->uspace_stack_size = STACK_SIZE _USER;95 kernel_uarg->uspace_stack_size = STACK_SIZE; 102 96 kernel_uarg->uspace_thread_function = NULL; 103 97 kernel_uarg->uspace_thread_arg = NULL; -
kernel/generic/src/proc/task.c
r1f7753a ra7f7ed12 196 196 task->ucycles = 0; 197 197 task->kcycles = 0; 198 199 task->silent_kill = false;200 198 201 199 task->ipc_info.call_sent = 0; -
uspace/lib/c/Makefile
r1f7753a ra7f7ed12 140 140 generic/net/socket_client.c \ 141 141 generic/net/socket_parse.c \ 142 generic/stack.c \143 142 generic/stacktrace.c \ 144 143 generic/arg_parse.c \ -
uspace/lib/c/generic/fibril.c
r1f7753a ra7f7ed12 37 37 #include <fibril.h> 38 38 #include <thread.h> 39 #include <stack.h>40 39 #include <tls.h> 41 40 #include <malloc.h> 42 #include <abi/mm/as.h>43 #include <as.h>44 41 #include <unistd.h> 45 42 #include <stdio.h> … … 49 46 #include <assert.h> 50 47 #include <async.h> 48 49 #ifndef FIBRIL_INITIAL_STACK_PAGES_NO 50 #define FIBRIL_INITIAL_STACK_PAGES_NO 1 51 #endif 51 52 52 53 /** … … 194 195 * stack member filled. 195 196 */ 196 as_area_destroy(stack);197 free(stack); 197 198 } 198 199 fibril_teardown(srcf->clean_after_me); … … 268 269 return 0; 269 270 270 size_t stack_size = stack_size_get(); 271 fibril->stack = as_area_create((void *) -1, stack_size, 272 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD | 273 AS_AREA_LATE_RESERVE); 274 if (fibril->stack == (void *) -1) { 271 fibril->stack = 272 (char *) malloc(FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize()); 273 if (!fibril->stack) { 275 274 fibril_teardown(fibril); 276 275 return 0; … … 282 281 context_save(&fibril->ctx); 283 282 context_set(&fibril->ctx, FADDR(fibril_main), fibril->stack, 284 stack_size, fibril->tcb);283 FIBRIL_INITIAL_STACK_PAGES_NO * getpagesize(), fibril->tcb); 285 284 286 285 return (fid_t) fibril; … … 299 298 fibril_t *fibril = (fibril_t *) fid; 300 299 301 as_area_destroy(fibril->stack);300 free(fibril->stack); 302 301 fibril_teardown(fibril); 303 302 } -
uspace/lib/c/generic/thread.c
r1f7753a ra7f7ed12 39 39 #include <abi/proc/uarg.h> 40 40 #include <fibril.h> 41 #include <stack.h>42 41 #include <str.h> 43 42 #include <async.h> … … 45 44 #include <as.h> 46 45 #include "private/thread.h" 46 47 #ifndef THREAD_INITIAL_STACK_PAGES 48 #define THREAD_INITIAL_STACK_PAGES 2 49 #endif 47 50 48 51 /** Main thread function. … … 98 101 return ENOMEM; 99 102 100 size_t stack_size = stack_size_get();103 size_t stack_size = getpagesize() * THREAD_INITIAL_STACK_PAGES; 101 104 void *stack = as_area_create(AS_AREA_ANY, stack_size, 102 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD | 103 AS_AREA_LATE_RESERVE); 105 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE); 104 106 if (stack == AS_MAP_FAILED) { 105 107 free(uarg);
Note:
See TracChangeset
for help on using the changeset viewer.
