FWIW: POSIX mq_send does not promise that the buffer is safe, it only
promises that the message is queued. Interesting interface.



On Wed, Jan 10, 2001 at 09:41:24AM +0100, Manfred Spraul wrote:
> > > In user space, how do you know when its safe to reuse the buffer that 
> > > was handed to sendmsg() with the MSG_NOCOPY flag? Or does sendmsg() 
> > > with that flag block until the buffer isn't needed by the kernel any 
> > > more? If it does block, doesn't that defeat the use of non-blocking 
> > > I/O? 
> > 
> > sendmsg() marks those pages COW and copies the original page into a new 
> > one for further usage. (the old page is used until the packet is 
> > released.) So for maximum performance user-space should not reuse such 
> > buffers immediately. 
> >
> That means sendmsg() changes the page tables? I measures
> smp_call_function on my Dual Pentium 350, and it took around 1950 cpu
> ticks.
> I'm sure that for an 8 way server the total lost time on all cpus (multi
> threaded server) is larger than the time required to copy the complete
> page.
> (I've attached my patch, just run "insmod dummy p_shift=0")
> 
> 
> --
>       Manfred
> --- 2.4/drivers/net/dummy.c   Mon Dec  4 02:45:22 2000
> +++ build-2.4/drivers/net/dummy.c     Wed Jan 10 09:15:20 2001
> @@ -95,9 +95,168 @@
>  
>  static struct net_device dev_dummy;
>  
> +/* ************************************* */
> +int p_shift = -1;
> +MODULE_PARM     (p_shift, "1i");
> +MODULE_PARM_DESC(p_shift, "Shift for the profile buffer");
> +
> +int p_size = 0;
> +MODULE_PARM     (p_size, "1i");
> +MODULE_PARM_DESC(p_size, "size");
> +
> +
> +#define STAT_TABLELEN                16384
> +static unsigned long totals[STAT_TABLELEN];
> +static unsigned int overflows;
> +
> +static unsigned long long stime;
> +static void start_measure(void)
> +{
> +      __asm__ __volatile__ (
> +             ".align 64\n\t"
> +             "pushal\n\t"
> +             "cpuid\n\t"
> +             "popal\n\t"
> +             "rdtsc\n\t"
> +             "movl %%eax,(%0)\n\t"
> +             "movl %%edx,4(%0)\n\t"
> +             : /* no output */
> +             : "c"(&stime)
> +             : "eax", "edx", "memory" );
> +}
> +
> +static void end_measure(void)
> +{
> +static unsigned long long etime;
> +     __asm__ __volatile__ (
> +             "pushal\n\t"
> +             "cpuid\n\t"
> +             "popal\n\t"
> +             "rdtsc\n\t"
> +             "movl %%eax,(%0)\n\t"
> +             "movl %%edx,4(%0)\n\t"
> +             : /* no output */
> +             : "c"(&etime)
> +             : "eax", "edx", "memory" );
> +     {
> +             unsigned long time = (unsigned long)(etime-stime);
> +             time >>= p_shift;
> +             if(time < STAT_TABLELEN) {
> +                     totals[time]++;
> +             } else {
> +                     overflows++;
> +             }
> +     }
> +}
> +
> +static void clean_buf(void)
> +{
> +     memset(totals,0,sizeof(totals));
> +     overflows = 0;
> +}
> +
> +static void print_line(unsigned long* array)
> +{
> +     int i;
> +     for(i=0;i<32;i++) {
> +             if((i%32)==16)
> +                     printk(":");
> +             printk("%lx ",array[i]); 
> +     }
> +}
> +
> +static void print_buf(char* caption)
> +{
> +     int i, other = 0;
> +     printk("Results - %s - shift %d",
> +             caption, p_shift);
> +
> +     for(i=0;i<STAT_TABLELEN;i+=32) {
> +             int j;
> +             int local = 0;
> +             for(j=0;j<32;j++)
> +                     local += totals[i+j];
> +
> +             if(local) {
> +                     printk("\n%3x: ",i);
> +                     print_line(&totals[i]);
> +                     other += local;
> +             }
> +     }
> +     printk("\nOverflows: %d.\n",
> +             overflows);
> +     printk("Sum: %ld\n",other+overflows);
> +}
> +
> +static void return_immediately(void* dummy)
> +{
> +     return;
> +}
> +
> +static void just_one_page(void* dummy)
> +{
> +     __flush_tlb_one(0x12345678);
> +     return;
> +}
> +
> +
>  static int __init dummy_init_module(void)
>  {
>       int err;
> +
> +     if(p_shift != -1) {
> +             int i;
> +             void* p;
> +             kmem_cache_t* cachep;
> +             /* empty test measurement: */
> +             printk("******** kernel cpu benchmark started **********\n");
> +             clean_buf();
> +             set_current_state(TASK_UNINTERRUPTIBLE);
> +             schedule_timeout(200);
> +             for(i=0;i<100;i++) {
> +                     start_measure();
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     end_measure();
> +             }
> +             print_buf("zero");
> +             clean_buf();
> +
> +             set_current_state(TASK_UNINTERRUPTIBLE);
> +             schedule_timeout(200);
> +             for(i=0;i<100;i++) {
> +                     start_measure();
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     smp_call_function(return_immediately,NULL,
> +                                             1, 1);
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     end_measure();
> +             }
> +             print_buf("empty smp_call_function()");
> +             clean_buf();
> +
> +             set_current_state(TASK_UNINTERRUPTIBLE);
> +             schedule_timeout(200);
> +             for(i=0;i<100;i++) {
> +                     start_measure();
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     smp_call_function(just_one_page,NULL,
> +                                             1, 1);
> +                     just_one_page(NULL);
> +                     return_immediately(NULL);
> +                     return_immediately(NULL);
> +                     end_measure();
> +             }
> +             print_buf("flush_one_page()");
> +             clean_buf();    
> +
> +             return -EINVAL;
> +     }
>  
>       dev_dummy.init = dummy_init;
>       SET_MODULE_OWNER(&dev_dummy);
> 


-- 
---------------------------------------------------------
Victor Yodaiken 
Finite State Machine Labs: The RTLinux Company.
 www.fsmlabs.com  www.rtlinux.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
Please read the FAQ at http://www.tux.org/lkml/

Reply via email to