From owner-p4-projects@FreeBSD.ORG Thu Jul 22 15:01:31 2010 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 07F3B1065674; Thu, 22 Jul 2010 15:01:31 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B8EE3106566B for ; Thu, 22 Jul 2010 15:01:30 +0000 (UTC) (envelope-from afiveg@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id A65FF8FC1C for ; Thu, 22 Jul 2010 15:01:30 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id o6MF1UUT069529 for ; Thu, 22 Jul 2010 15:01:30 GMT (envelope-from afiveg@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id o6MF1UMB069527 for perforce@freebsd.org; Thu, 22 Jul 2010 15:01:30 GMT (envelope-from afiveg@FreeBSD.org) Date: Thu, 22 Jul 2010 15:01:30 GMT Message-Id: <201007221501.o6MF1UMB069527@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to afiveg@FreeBSD.org using -f From: Alexandre Fiveg To: Perforce Change Reviews Precedence: bulk Cc: Subject: PERFORCE change 181315 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 22 Jul 2010 15:01:31 -0000 http://p4web.freebsd.org/@@181315?ac=10 Change 181315 by afiveg@ringmap-2 on 2010/07/22 15:01:28 Porting ringmap to the 10GbE. ringmap_open(), ringmap_close() work properly. In the function ixgbe_initialize_receive_units() I set in the all RETA-table entries the default queue number. So, all packets will post to the one specific queue. I do this hack in order to make the port to 10G easier: with only one queue works ringmap like by 1Gb adapter. Affected files ... .. //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ixgbe.c#6 edit .. //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ixgbe.h#5 edit .. //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_8259.h#4 edit .. //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_ixgbe.c#5 edit .. //depot/projects/soc2010/ringmap/current/sys/net/ringmap.c#35 edit .. //depot/projects/soc2010/ringmap/current/sys/net/ringmap.h#35 edit .. //depot/projects/soc2010/ringmap/current/sys/net/ringmap_kernel.h#5 edit .. //depot/projects/soc2010/ringmap/tests/ringmap/close.c#4 edit .. //depot/projects/soc2010/ringmap/tests/ringmap/ioctl.c#4 edit .. //depot/projects/soc2010/ringmap/tests/ringmap/main.c#6 edit .. //depot/projects/soc2010/ringmap/tests/ringmap/mmap.c#6 edit .. //depot/projects/soc2010/ringmap/tests/ringmap/open.c#6 edit Differences ... ==== //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ixgbe.c#6 (text+ko) ==== @@ -211,7 +211,7 @@ extern int ringmap_attach (device_t, struct ringmap_functions *); extern int ringmap_detach (device_t); -extern struct ringmap_functions ringmap_f; +extern struct ringmap_functions ringmap_8259_f; #endif @@ -657,7 +657,7 @@ #ifdef RINGMAP - ringmap_attach(dev, &ringmap_f); + ringmap_attach(dev, &ringmap_8259_f); #endif INIT_DEBUGOUT("ixgbe_attach: end"); @@ -1336,7 +1336,7 @@ IXGBE_TX_UNLOCK(txr); #ifdef RINGMAP - adapter->rm->funcs->sync_head(adapter->dev); + adapter->rm->funcs->sync_head(que); /* Wakeup threads with not empty rings */ SLIST_FOREACH(co, &adapter->rm->object_list, objects) { @@ -1346,7 +1346,6 @@ } #endif - if (more) { taskqueue_enqueue(que->tq, &que->que_task); return; @@ -1433,7 +1432,6 @@ #endif ++que->irqs; - more_rx = ixgbe_rxeof(que, adapter->rx_process_limit); IXGBE_TX_LOCK(txr); @@ -1443,7 +1441,7 @@ more_rx = ixgbe_rxeof(que, adapter->rx_process_limit); #ifdef RINGMAP - adapter->rm->funcs->sync_head(adapter->dev); + adapter->rm->funcs->sync_head(que); /* Wakeup threads with not empty rings */ SLIST_FOREACH(co, &adapter->rm->object_list, objects) { @@ -1453,7 +1451,6 @@ } #endif - /* Do AIM now? */ if (ixgbe_enable_aim == FALSE) @@ -3930,9 +3927,18 @@ /* Set up the redirection table */ for (i = 0, j = 0; i < 128; i++, j++) { if (j == adapter->num_queues) j = 0; +#ifndef RINGMAP + reta = (reta << 8) | (j * 0x11); +#else +#ifdef DEFAULT_QUEUE + reta = (reta << 8) | (DEFAULT_QUEUE * 0x11); +#else reta = (reta << 8) | (j * 0x11); +#endif +#endif if ((i & 3) == 3) IXGBE_WRITE_REG(hw, IXGBE_RETA(i >> 2), reta); + } /* Now fill our hash function seeds */ ==== //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ixgbe.h#5 (text+ko) ==== ==== //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_8259.h#4 (text+ko) ==== @@ -3,18 +3,13 @@ /* Kernel address of mbuf wich placed in the slot "i" */ -#define GET_MBUF_P(que) \ - (MBUF_AREA(que)[(que)->rxr->me].m_head) +#define GET_MBUF_P(que, num) \ + (MBUF_AREA(que)[(num)].m_pack) /* Kernel address of the packet wich placed in the slot "i" */ -#define GET_PACKET_P(que) \ - (MBUF_AREA(que)[(que)->rxr->me].m_head->m_data) - - -/* Kernel address of the descriptor wich placed in the slot "i" */ -#define GET_DESCRIPTOR_P(que) \ - (&(DESC_AREA(que)[(que)->rxr->me])) +#define GET_PACKET_P(que, num) \ + (MBUF_AREA(que)[(num)].m_pack->m_data) /* Registers access */ @@ -30,7 +25,7 @@ RINGMAP_HW_READ_REG(HW_STRUCT(que), (reg)) #define HW_WRITE_REG(que, reg, val) \ - RINGMAP_HW_READ_REG(HW_STRUCT(que), (reg), (val)) + RINGMAP_HW_WRITE_REG(HW_STRUCT(que), (reg), (val)) #define RINGMAP_HW_READ_HEAD(que) \ HW_READ_REG((que), HW_RDH(que)) @@ -38,12 +33,11 @@ #define RINGMAP_HW_SYNC_HEAD(que, ring) \ SW_HEAD(ring) = RINGMAP_HW_READ_HEAD(que); -#define RINGMAP_HW_SYNC_TAIL(que, ring) \ - HW_WRITE_REG((que), HW_RDT(que), SW_TAIL(ring)) - #define RINGMAP_HW_WRITE_TAIL(que, val) \ HW_WRITE_REG((que), HW_RDT(que), (val)) +#define RINGMAP_HW_SYNC_TAIL(que, ring) \ + RINGMAP_HW_WRITE_TAIL((que), SW_TAIL(ring)) + #define RINGMAP_HW_READ_TAIL(que) \ HW_READ_REG((que), HW_RDT(que)) - ==== //depot/projects/soc2010/ringmap/current/sys/dev/ixgbe/ringmap_ixgbe.c#5 (text+ko) ==== @@ -23,14 +23,19 @@ device_t rm_8259_get_device_p(struct cdev *); void rm_8259_enable_intr(device_t); void rm_8259_disable_intr(device_t); -int rm_8259_set_slot(struct ring *, device_t, unsigned int); +int rm_8259_set_slot(struct ring *, void *, unsigned int); +int rm_8259_set_queue(struct capt_object *, unsigned int); void rm_8259_interrupt(void *); void rm_8259_delayed_interrupt(void *); int rm_8259_print_ring_pointers(void *); -void rm_8259_sync_head_tail(device_t); -void rm_8259_sync_tail(device_t); -void rm_8259_sync_head(device_t); +void rm_8259_sync_head_tail(void *); +void rm_8259_sync_tail(void *); +void rm_8259_sync_head(void *); void rm_8259_delayed_interrupt_per_packet(void *, int); +void rm_8259_disable_receive(void *); +void rm_8259_enable_receive(void *); +struct ix_queue * rm_8259_get_free_queue(device_t); +struct capt_object * get_capt_obj(void *context); extern devclass_t ixgbe_devclass; extern void ixgbe_enable_intr(struct adapter *); @@ -39,7 +44,7 @@ extern void print_capt_obj(struct capt_object *); -struct ringmap_functions ringmap_f = { +struct ringmap_functions ringmap_8259_f = { rm_8259_set_ringmap_to_adapter, rm_8259_enable_intr, rm_8259_disable_intr, @@ -50,6 +55,7 @@ rm_8259_sync_tail, rm_8259_sync_head, rm_8259_set_slot, + rm_8259_set_queue, rm_8259_get_ringmap_p, rm_8259_get_device_p }; @@ -84,36 +90,65 @@ * 2. SYNC_TAIL: RDT = ring->userrp */ void -rm_8259_sync_head_tail(device_t dev) +rm_8259_sync_head_tail(void *context) { - rm_8259_sync_tail(dev); - rm_8259_sync_head(dev); + rm_8259_sync_tail(context); + rm_8259_sync_head(context); } void -rm_8259_sync_tail(device_t dev) +rm_8259_sync_tail(void *context) { - struct adapter *adapter; - adapter = (struct adapter *)device_get_softc(dev); + struct ix_queue *que = (struct ix_queue *)context; + struct adapter *adapter = que->adapter; + struct capt_object *co = NULL; - - + RINGMAP_LOCK(adapter->rm); + if (adapter->rm->open_cnt) { + co = get_capt_obj(que); + if (co != NULL) { + RINGMAP_HW_SYNC_TAIL(que, co->ring); + } + } + RINGMAP_UNLOCK(adapter->rm); } void -rm_8259_sync_head(device_t dev) +rm_8259_sync_head(void *context) { - struct adapter *adapter; + struct ix_queue *que = (struct ix_queue *)context; + struct adapter *adapter = que->adapter; + struct capt_object *co = NULL; + RINGMAP_LOCK(adapter->rm); + if (adapter->rm->open_cnt) { + co = get_capt_obj(que); + if (co != NULL) { + RINGMAP_HW_SYNC_HEAD(que, co->ring); + } else { + RINGMAP_ERROR(There is no capturing object associated with queue); + } + } + RINGMAP_UNLOCK(adapter->rm); +} - adapter = (struct adapter *)device_get_softc(dev); - RINGMAP_LOCK(adapter->rm); +struct capt_object * +get_capt_obj(void *queue) +{ + struct ix_queue *que = (struct ix_queue *)queue; + struct adapter *adapter = que->adapter; + struct ringmap *rm = adapter->rm; + struct capt_object *co = NULL; - RINGMAP_UNLOCK(adapter->rm); + SLIST_FOREACH(co, &rm->object_list, objects) { + if (co->que == que) + return (co); + } + return (co); } @@ -138,16 +173,20 @@ struct ix_queue *que = (struct ix_queue *)context; struct adapter *adapter = (struct adapter *)que->adapter; struct timeval last_ts; + struct capt_object *co = NULL; RINGMAP_LOCK(adapter->rm); - if ( adapter->rm->open_cnt > 0 ) { - - adapter->rm->interrupts_counter++; - getmicrotime(&last_ts); - rm_8259_sync_tail(adapter->dev); + co = get_capt_obj(que); + if (co != NULL) { + adapter->rm->interrupts_counter++; + getmicrotime(&last_ts); + co->ring->last_ts = last_ts; + rm_8259_sync_tail(context); + } else { + RINGMAP_ERROR(There is no capturing object associated with queue); + } } - RINGMAP_UNLOCK(adapter->rm); } @@ -158,6 +197,7 @@ struct ix_queue *que = (struct ix_queue *)context; struct adapter *adapter = (struct adapter *)que->adapter; struct ringmap *rm = adapter->rm;; + struct capt_object *co = NULL; RINGMAP_INTR(start); @@ -166,6 +206,15 @@ #if (RINGMAP_INTR_DEB) rm_8259_print_ring_pointers(que); #endif + if (adapter->rm->open_cnt) { + co = get_capt_obj(que); + if (co != NULL) { + co->ring->slot[slot_num].intr_num = que->irqs; + co->ring->slot[slot_num].ts = co->ring->last_ts; + } else { + RINGMAP_ERROR(There is no capturing object associated with queue); + } + } RINGMAP_UNLOCK(rm); @@ -174,18 +223,45 @@ int -rm_8259_set_slot(struct ring *ring, device_t dev, unsigned int slot_num) +rm_8259_set_slot(struct ring *ring, void *context, unsigned int slot_num) { - struct adapter *adapter = NULL; - adapter = (struct adapter *)device_get_softc(dev); + struct ix_queue *que = (struct ix_queue *)context; #if (__RINGMAP_DEB) printf("[%s] Set slot: %d\n", __func__, slot_num); #endif + if (que == NULL) { + RINGMAP_ERROR(Null pointer to the queue); + goto fail; + } + /* First check pointers */ +//TODO; + if (GET_MBUF_P(que, slot_num) == NULL){ + RINGMAP_ERROR(Pointer to mbuf is NULL); + goto fail; + } + if (GET_PACKET_P(que, slot_num) == NULL){ + RINGMAP_ERROR(Pointer to packet is NULL); + goto fail; + } + + /* Now if everything is Ok, we can initialize ring pointers */ + ring->slot[slot_num].mbuf.kern = + (vm_offset_t)GET_MBUF_P(que, slot_num); + ring->slot[slot_num].mbuf.phys = + (vm_paddr_t)vtophys(GET_MBUF_P(que, slot_num)); + ring->slot[slot_num].packet.kern = + (vm_offset_t)GET_PACKET_P(que, slot_num); + ring->slot[slot_num].packet.phys = + (vm_paddr_t)vtophys(GET_PACKET_P(que, slot_num)); + return (0); +fail: + + return (-1); } @@ -255,6 +331,90 @@ } +void +rm_8259_disable_receive(void *context) +{ + u32 rxctrl; + + struct ix_queue *que = (struct ix_queue *)context; + struct adapter *adapter = (struct adapter *)que->adapter; + struct ixgbe_hw *hw = &adapter->hw; + + rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, + rxctrl & ~IXGBE_RXCTRL_RXEN); +} + + +void +rm_8259_enable_receive(void *context) +{ + u32 rxctrl; + + struct ix_queue *que = (struct ix_queue *)context; + struct adapter *adapter = (struct adapter *)que->adapter; + struct ixgbe_hw *hw = &adapter->hw; + + rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL); + IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, + rxctrl | IXGBE_RXCTRL_RXEN); +} + + +struct ix_queue * +rm_8259_get_free_queue(device_t dev) +{ + struct adapter *adapter; + struct ringmap *rm =NULL; + struct ix_queue *que = NULL; + struct capt_object *co = NULL; + int i, j = 1; + + adapter = (struct adapter *)device_get_softc(dev); + que = adapter->queues; + rm = adapter->rm; + + /* + * Look for the queue that is not used by any capturing object (co) + */ + for (i = 0; (i < adapter->num_queues); i++, que++) { + j = 0; + SLIST_FOREACH(co, &rm->object_list, objects) { + j += (co->que == que); + } + if (j == 0) + return (que); + } + + return (NULL); +} + + +int +rm_8259_set_queue(struct capt_object *co, unsigned int queue_num) +{ + device_t dev; + struct adapter *adapter; + int err = -1; + + if (co->rm != NULL) { + dev = co->rm->dev; + adapter = (struct adapter *)device_get_softc(dev); + + if (queue_num < adapter->num_queues) { + co->que = &adapter->queues[queue_num]; + err = 0; + } else { + RINGMAP_ERROR(Wrong queue number); + } + } else { + RINGMAP_ERROR(Capturing object is not associated with ringmap); + } + + return (err); +} + + int rm_8259_print_ring_pointers(void *context) { ==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap.c#35 (text+ko) ==== @@ -100,7 +100,7 @@ /* Store adapters device structure */ rm->dev = dev; - /* Initialize the list of capturing instances */ + /* Initialize the list of capturing objects */ SLIST_INIT(&rm->object_list); /* Init the mutex to protecting our data */ @@ -155,7 +155,7 @@ int ringmap_open(struct cdev *cdev, int flag, int otyp, struct thread *td) { - int err = 0, i = 0; + int err = 0, i=i; struct ringmap *rm = NULL; struct ring *ring = NULL; struct capt_object *co = NULL; @@ -163,7 +163,7 @@ RINGMAP_FUNC_DEBUG(start); #if (__RINGMAP_DEB) - printf("[%s] pid = %d\n", __func__, td->td_proc->p_pid); + printf(RINGMAP_PREFIX"[%s] pid = %d\n", __func__, td->td_proc->p_pid); #endif /* a little magic */ @@ -176,13 +176,14 @@ RINGMAP_LOCK(rm); + /* TODO: set max number of threads in the ringmap struct as a variable */ if (rm->open_cnt == RINGMAP_MAX_THREADS){ RINGMAP_ERROR(Can not open device!); err = EIO; goto out; } - /* check: the current thread shouldn't open(2) more than one time */ + /* check: the current thread shouldn't open more than one time */ if (rm->open_cnt) { SLIST_FOREACH(co, &rm->object_list, objects) { if (co->td == td) { @@ -204,18 +205,7 @@ err = EIO; goto out; } - for (i = 0 ; i < SLOTS_NUMBER ; i++){ - if (rm->funcs->set_slot(ring, rm->dev, i) == -1){ - RINGMAP_ERROR(Ring initialization failed!); - contigfree(ring, sizeof(struct ring), M_DEVBUF); - err = EIO; goto out; - } - } - - ring->size = SLOTS_NUMBER; - ring->pid = td->td_proc->p_pid; - /* * create the capturing instance wich will represent * current thread and packets ring @@ -227,10 +217,30 @@ err = EIO; goto out; } + + ring->size = SLOTS_NUMBER; + ring->pid = td->td_proc->p_pid; + co->ring = ring; co->td = td; co->rm = rm; + /* The next should be probably done in the ioctl() */ +#ifdef DEFAULT_QUEUE + rm->funcs->set_queue(co, DEFAULT_QUEUE); + for (i = 0 ; i < SLOTS_NUMBER ; i++){ + if (rm->funcs->set_slot(ring, co->que, i) == -1){ + RINGMAP_ERROR(Ring initialization failed!); + contigfree(ring, sizeof(struct ring), M_DEVBUF); + + err = EIO; goto out; + } +#if (__RINGMAP_DEB) + PRINT_SLOT(ring, i); +#endif + } +#endif + SLIST_INSERT_HEAD(&rm->object_list, co, objects); /* @@ -244,15 +254,15 @@ err = EIO; goto out; } - - rm->funcs->sync_head_tail(rm->dev); + + rm->funcs->sync_head_tail(co->que); + rm->open_cnt++; + #if (__RINGMAP_DEB) print_capt_obj(co); PRINT_RING_PTRS(co->ring); #endif - rm->open_cnt++; - out: RINGMAP_UNLOCK(rm); @@ -261,6 +271,8 @@ return (err); } + + int ringmap_close(struct cdev *cdev, int flag, int otyp, struct thread *td) { @@ -268,7 +280,7 @@ RINGMAP_FUNC_DEBUG(start); #if (__RINGMAP_DEB) - printf("[%s] pid = %d\n", __func__, td->td_proc->p_pid); + printf(RINGMAP_PREFIX"[%s] pid = %d\n", __func__, td->td_proc->p_pid); #endif RINGMAP_FUNC_DEBUG(end); @@ -424,7 +436,7 @@ case IOCTL_SLEEP_WAIT: co->ring->user_wait_kern++; - rm->funcs->sync_head_tail(rm->dev); + rm->funcs->sync_head_tail(co->que); #if (__RINGMAP_DEB) print_capt_obj(co); @@ -443,12 +455,12 @@ break; case IOCTL_SYNC_HEAD_TAIL: - rm->funcs->sync_head_tail(rm->dev); + rm->funcs->sync_head_tail(co->que); break; /* Synchronize sowftware ring-tail with hardware-ring-tail (RDT) */ case IOCTL_SYNC_TAIL: - rm->funcs->sync_tail(rm->dev); + rm->funcs->sync_tail(co->que); break; default: @@ -501,10 +513,13 @@ print_capt_obj(struct capt_object *co) { if (co != NULL) { - printf("[%s] co->td->proc->pid: %d\n", - __func__, co->td->td_proc->p_pid); + printf("=== co->td->proc->pid: %d\n", + co->td->td_proc->p_pid); + + printf("=== Ring Kernel Addr:0x%X\n", + (unsigned int)co->ring); - printf("[%s] Ring Kernel Addr:0x%X\n", - __func__, (unsigned int)co->ring); + printf("=== Queue Kernel Addr:0x%X\n", + (unsigned int)co->que); } } ==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap.h#35 (text+ko) ==== @@ -8,6 +8,11 @@ */ #define RINGMAP_DEVICE "ringmap" +/* + * Default queue number + */ +#define DEFAULT_QUEUE 0 + /* * Driver works only with device wich has the following device ID. If 0 * then work with all devices that was found and accepted in the "probe" @@ -23,6 +28,8 @@ /* 1 - enable time stamping in the driver */ #define RINGMAP_TIMESTAMP 1 +/* TODO: should not be as macro */ +#define RINGMAP_MAX_THREADS 8 struct address { vm_paddr_t phys; ==== //depot/projects/soc2010/ringmap/current/sys/net/ringmap_kernel.h#5 (text+ko) ==== @@ -1,9 +1,11 @@ struct ringmap_functions; struct capt_object { - struct thread *td; - struct ring *ring; - struct ringmap *rm; + struct ringmap *rm; + struct thread *td; + + struct ring *ring; + void *que; SLIST_ENTRY(capt_object) objects; }; @@ -98,14 +100,18 @@ * the value of ring->userrp. Kernel will check this value and set it * into the hardware TAIL-register. */ - void (*sync_head_tail)(device_t); - void (*sync_tail)(device_t); - void (*sync_head)(device_t); + void (*sync_head_tail)(void *); + void (*sync_tail)(void *); + void (*sync_head)(void *); /* Initialize the ring slot */ - int (*set_slot)(struct ring *, device_t, unsigned int); + int (*set_slot)(struct ring *, void *, unsigned int); + + /* Associate the capturing objec with a hardware queue */ + int (*set_queue)(struct capt_object *, unsigned int); struct ringmap *(*dev_to_ringmap)(device_t); + device_t (*cdev_to_dev)(struct cdev *); }; ==== //depot/projects/soc2010/ringmap/tests/ringmap/close.c#4 (text+ko) ==== ==== //depot/projects/soc2010/ringmap/tests/ringmap/ioctl.c#4 (text+ko) ==== ==== //depot/projects/soc2010/ringmap/tests/ringmap/main.c#6 (text+ko) ==== @@ -23,7 +23,7 @@ exit (1); } - rm_mmap(fd); + // rm_mmap(fd); rm_close(fd); return (0); ==== //depot/projects/soc2010/ringmap/tests/ringmap/mmap.c#6 (text+ko) ==== ==== //depot/projects/soc2010/ringmap/tests/ringmap/open.c#6 (text+ko) ====