Diff for /src/sys/kern/uipc_syscalls.c between versions 1.20 and 1.21

version 1.20, 2003/10/15 08:43:37 version 1.21, 2003/12/10 22:26:19
Line 74 Line 74
   
 static void sf_buf_init(void *arg);  static void sf_buf_init(void *arg);
 SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL)  SYSINIT(sock_sf, SI_SUB_MBUF, SI_ORDER_ANY, sf_buf_init, NULL)
static SLIST_HEAD(, sf_buf) sf_freelist;
 LIST_HEAD(sf_buf_list, sf_buf);
 
 /*
  * A hash table of active sendfile(2) buffers
  */
 static struct sf_buf_list *sf_buf_hashtable;
 static u_long sf_buf_hashmask;
 
 #define SF_BUF_HASH(m)  (((m) - vm_page_array) & sf_buf_hashmask)
 
 static TAILQ_HEAD(, sf_buf) sf_buf_freelist;
 static u_int sf_buf_alloc_want;
 
 static vm_offset_t sf_base;  static vm_offset_t sf_base;
 static struct sf_buf *sf_bufs;  static struct sf_buf *sf_bufs;
 static int sf_buf_alloc_want;  
   
 /*  /*
  * System call interface to the socket abstraction.   * System call interface to the socket abstraction.
Line 1238  sf_buf_init(void *arg) Line 1250  sf_buf_init(void *arg)
 {  {
         int i;          int i;
   
        SLIST_INIT(&sf_freelist);        sf_buf_hashtable = hashinit(nsfbufs, M_TEMP, &sf_buf_hashmask);
         TAILQ_INIT(&sf_buf_freelist);
         sf_base = kmem_alloc_pageable(kernel_map, nsfbufs * PAGE_SIZE);          sf_base = kmem_alloc_pageable(kernel_map, nsfbufs * PAGE_SIZE);
        sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP, M_NOWAIT);        sf_bufs = malloc(nsfbufs * sizeof(struct sf_buf), M_TEMP,
        bzero(sf_bufs, nsfbufs * sizeof(struct sf_buf));            M_NOWAIT | M_ZERO);
         for (i = 0; i < nsfbufs; i++) {          for (i = 0; i < nsfbufs; i++) {
                 sf_bufs[i].kva = sf_base + i * PAGE_SIZE;                  sf_bufs[i].kva = sf_base + i * PAGE_SIZE;
                SLIST_INSERT_HEAD(&sf_freelist, &sf_bufs[i], free_list);                TAILQ_INSERT_TAIL(&sf_buf_freelist, &sf_bufs[i], free_entry);
         }          }
 }  }
   
Line 1252  sf_buf_init(void *arg) Line 1265  sf_buf_init(void *arg)
  * Get an sf_buf from the freelist. Will block if none are available.   * Get an sf_buf from the freelist. Will block if none are available.
  */   */
 struct sf_buf *  struct sf_buf *
sf_buf_alloc()sf_buf_alloc(struct vm_page *m)
 {  {
           struct sf_buf_list *hash_chain;
         struct sf_buf *sf;          struct sf_buf *sf;
         int s;          int s;
         int error;          int error;
   
         s = splimp();          s = splimp();
        while ((sf = SLIST_FIRST(&sf_freelist)) == NULL) {        hash_chain = &sf_buf_hashtable[SF_BUF_HASH(m)];
                sf_buf_alloc_want = 1;        LIST_FOREACH(sf, hash_chain, list_entry) {
                error = tsleep(&sf_freelist, PCATCH, "sfbufa", 0);                if (sf->m == m) {
                if (error)                        if (sf->refcnt == 0) {
                        break;                                /* reclaim cached entry off freelist */
                                 TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
                         }
                         ++sf->refcnt;
                         goto done;      /* found existing mapping */
                 }
         }          }
        if (sf != NULL) {
                SLIST_REMOVE_HEAD(&sf_freelist, free_list);        /*
                sf->refcnt = 1;         * Didn't find old mapping.  Get a buffer off the freelist.
          */
         while ((sf = TAILQ_FIRST(&sf_buf_freelist)) == NULL) {
                 ++sf_buf_alloc_want;
                 error = tsleep(&sf_buf_freelist, PCATCH, "sfbufa", 0);
                 --sf_buf_alloc_want;
 
                 /* If we got a signal, don't risk going back to sleep. */
                 if (error)
                         goto done;
         }          }
           TAILQ_REMOVE(&sf_buf_freelist, sf, free_entry);
   
           if (sf->m != NULL)      /* remove previous mapping from hash table */
                   LIST_REMOVE(sf, list_entry);
           LIST_INSERT_HEAD(hash_chain, sf, list_entry);
           sf->refcnt = 1;
           sf->m = m;
           pmap_qenter(sf->kva, &sf->m, 1);
   done:
         splx(s);          splx(s);
         return (sf);          return (sf);
 }  }
   
 #define dtosf(x)        (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT])  #define dtosf(x)        (&sf_bufs[((uintptr_t)(x) - (uintptr_t)sf_base) >> PAGE_SHIFT])
   
 void  void
 sf_buf_ref(caddr_t addr, u_int size)  sf_buf_ref(caddr_t addr, u_int size)
 {  {
Line 1303  sf_buf_free(caddr_t addr, u_int size) Line 1341  sf_buf_free(caddr_t addr, u_int size)
                 panic("sf_buf_free: freeing free sf_buf");                  panic("sf_buf_free: freeing free sf_buf");
         sf->refcnt--;          sf->refcnt--;
         if (sf->refcnt == 0) {          if (sf->refcnt == 0) {
                 pmap_qremove((vm_offset_t)addr, 1);  
                 m = sf->m;                  m = sf->m;
                 s = splvm();                  s = splvm();
                 vm_page_unwire(m, 0);                  vm_page_unwire(m, 0);
Line 1315  sf_buf_free(caddr_t addr, u_int size) Line 1352  sf_buf_free(caddr_t addr, u_int size)
                 if (m->wire_count == 0 && m->object == NULL)                  if (m->wire_count == 0 && m->object == NULL)
                         vm_page_free(m);                          vm_page_free(m);
                 splx(s);                  splx(s);
                sf->m = NULL;
                SLIST_INSERT_HEAD(&sf_freelist, sf, free_list);                TAILQ_INSERT_TAIL(&sf_buf_freelist, sf, free_entry);
                if (sf_buf_alloc_want) {                if (sf_buf_alloc_want > 0)
                        sf_buf_alloc_want = 0;                        wakeup_one(&sf_buf_freelist);
                        wakeup(&sf_freelist); 
                } 
         }          }
 }  }
   
Line 1607  retry_lookup: Line 1642  retry_lookup:
                  * Get a sendfile buf. We usually wait as long as necessary,                   * Get a sendfile buf. We usually wait as long as necessary,
                  * but this wait can be interrupted.                   * but this wait can be interrupted.
                  */                   */
                if ((sf = sf_buf_alloc()) == NULL) {                if ((sf = sf_buf_alloc(pg)) == NULL) {
                         s = splvm();                          s = splvm();
                         vm_page_unwire(pg, 0);                          vm_page_unwire(pg, 0);
                         if (pg->wire_count == 0 && pg->object == NULL)                          if (pg->wire_count == 0 && pg->object == NULL)
Line 1618  retry_lookup: Line 1653  retry_lookup:
                         goto done;                          goto done;
                 }                  }
   
   
                 /*  
                  * Allocate a kernel virtual page and insert the physical page  
                  * into it.  
                  */  
   
                 sf->m = pg;  
                 pmap_qenter(sf->kva, &pg, 1);  
                 /*                  /*
                  * Get an mbuf header and set it up as having external storage.                   * Get an mbuf header and set it up as having external storage.
                  */                   */

Removed from v.1.20  
changed lines
  Added in v.1.21