r15529: Initialise our saved uid and gid so that we can tell when
[vlendec/samba-autobuild/.git] / source3 / profile / profile.c
index 87f5e2c9b22e2b824c7852fca0e74c4c31ec8ec5..ba9596301c6491d3a25e615b34749c5a8d903337 100644 (file)
@@ -1,6 +1,5 @@
 /* 
-   Unix SMB/Netbios implementation.
-   Version 1.9.
+   Unix SMB/CIFS implementation.
    store smbd profiling information in shared memory
    Copyright (C) Andrew Tridgell 1999
    
 
 #include "includes.h"
 
-#include <sys/shm.h>
-
-extern int DEBUGLEVEL;
-
-#define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6))
+#ifdef WITH_PROFILE
+#define IPC_PERMS ((S_IRUSR | S_IWUSR) | S_IRGRP | S_IROTH)
+#endif /* WITH_PROFILE */
 
+#ifdef WITH_PROFILE
 static int shm_id;
 static BOOL read_only;
+#if defined(HAVE_CLOCK_GETTIME)
+clockid_t __profile_clock;
+#endif
+#endif
 
-struct profile_struct *profile_p;
+struct profile_header *profile_h;
+struct profile_stats *profile_p;
 
 BOOL do_profile_flag = False;
 BOOL do_profile_times = False;
 
-struct timeval profile_starttime;
-struct timeval profile_endtime;
-
 /****************************************************************************
 receive a set profile level message
 ****************************************************************************/
-void profile_message(int msg_type, pid_t src, void *buf, size_t len)
+void profile_message(int msg_type, struct process_id src, void *buf, size_t len)
 {
         int level;
 
        memcpy(&level, buf, sizeof(int));
+#ifdef WITH_PROFILE
        switch (level) {
-       case 0:
+       case 0:         /* turn off profiling */
                do_profile_flag = False;
                do_profile_times = False;
+               DEBUG(1,("INFO: Profiling turned OFF from pid %d\n",
+                        (int)procid_to_pid(&src)));
                break;
-       case 1:
+       case 1:         /* turn on counter profiling only */
                do_profile_flag = True;
                do_profile_times = False;
+               DEBUG(1,("INFO: Profiling counts turned ON from pid %d\n",
+                        (int)procid_to_pid(&src)));
                break;
-       case 2:
+       case 2:         /* turn on complete profiling */
                do_profile_flag = True;
                do_profile_times = True;
+               DEBUG(1,("INFO: Full profiling turned ON from pid %d\n",
+                        (int)procid_to_pid(&src)));
+               break;
+       case 3:         /* reset profile values */
+               memset((char *)profile_p, 0, sizeof(*profile_p));
+               DEBUG(1,("INFO: Profiling values cleared from pid %d\n",
+                        (int)procid_to_pid(&src)));
                break;
        }
-       DEBUG(1,("Profile level set to %d from pid %d\n", level, (int)src));
+#else /* WITH_PROFILE */
+       DEBUG(1,("INFO: Profiling support unavailable in this build.\n"));
+#endif /* WITH_PROFILE */
+}
+
+/****************************************************************************
+receive a request profile level message
+****************************************************************************/
+void reqprofile_message(int msg_type, struct process_id src,
+                       void *buf, size_t len)
+{
+        int level;
+
+#ifdef WITH_PROFILE
+       level = 1 + (do_profile_flag?2:0) + (do_profile_times?4:0);
+#else
+       level = 0;
+#endif
+       DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n",
+                (unsigned int)procid_to_pid(&src)));
+       message_send_pid(src, MSG_PROFILELEVEL, &level, sizeof(int), True);
 }
 
 /*******************************************************************
   open the profiling shared memory area
   ******************************************************************/
+#ifdef WITH_PROFILE
 BOOL profile_setup(BOOL rdonly)
 {
        struct shmid_ds shm_ds;
 
        read_only = rdonly;
 
+#if defined(HAVE_CLOCK_GETTIME)
+       if (this_is_smp()) {
+               /* This is faster that gettimeofday, but not fast enough to
+                * leave it enabled in production.
+                */
+               __profile_clock = CLOCK_MONOTONIC;
+       } else {
+               /* CLOCK_PROCESS_CPUTIME_ID is sufficiently fast that the
+                * always profiling times is plausible. Unfortunately it is
+                * only accurate if we can guarantee we will not be scheduled
+                * onto a different CPU between samples. Until there is some
+                * way to set processor affinity, we can only use this on
+                * uniprocessors.
+                */
+               __profile_clock = CLOCK_PROCESS_CPUTIME_ID;
+       }
+#endif
+
  again:
        /* try to use an existing key */
        shm_id = shmget(PROF_SHMEM_KEY, 0, 0);
@@ -81,7 +132,7 @@ BOOL profile_setup(BOOL rdonly)
           if we are running from inetd. Bad luck. */
        if (shm_id == -1) {
                if (read_only) return False;
-               shm_id = shmget(PROF_SHMEM_KEY, sizeof(*profile_p), 
+               shm_id = shmget(PROF_SHMEM_KEY, sizeof(*profile_h), 
                                IPC_CREAT | IPC_EXCL | IPC_PERMS);
        }
        
@@ -92,7 +143,7 @@ BOOL profile_setup(BOOL rdonly)
        }   
        
        
-       profile_p = (struct profile_struct *)shmat(shm_id, 0, 
+       profile_h = (struct profile_header *)shmat(shm_id, 0, 
                                                   read_only?SHM_RDONLY:0);
        if ((long)profile_p == -1) {
                DEBUG(0,("Can't attach to IPC area. Error was %s\n", 
@@ -107,14 +158,18 @@ BOOL profile_setup(BOOL rdonly)
                return False;
        }
 
-       if (shm_ds.shm_perm.cuid != 0 || shm_ds.shm_perm.cgid != 0) {
-               DEBUG(0,("ERROR: root did not create the shmem\n"));
+       if (shm_ds.shm_perm.cuid != sec_initial_uid() ||
+           shm_ds.shm_perm.cgid != sec_initial_gid()) {
+               DEBUG(0,("ERROR: we did not create the shmem "
+                        "(owned by another user, uid %u, gid %u)\n",
+                        shm_ds.shm_perm.cuid,
+                        shm_ds.shm_perm.cgid));
                return False;
        }
 
-       if (shm_ds.shm_segsz != sizeof(*profile_p)) {
+       if (shm_ds.shm_segsz != sizeof(*profile_h)) {
                DEBUG(0,("WARNING: profile size is %d (expected %d). Deleting\n",
-                        (int)shm_ds.shm_segsz, sizeof(*profile_p)));
+                        (int)shm_ds.shm_segsz, sizeof(*profile_h)));
                if (shmctl(shm_id, IPC_RMID, &shm_ds) == 0) {
                        goto again;
                } else {
@@ -123,13 +178,15 @@ BOOL profile_setup(BOOL rdonly)
        }
 
        if (!read_only && (shm_ds.shm_nattch == 1)) {
-               memset((char *)profile_p, 0, sizeof(*profile_p));
-               profile_p->prof_shm_magic = PROF_SHM_MAGIC;
-               profile_p->prof_shm_version = PROF_SHM_VERSION;
+               memset((char *)profile_h, 0, sizeof(*profile_h));
+               profile_h->prof_shm_magic = PROF_SHM_MAGIC;
+               profile_h->prof_shm_version = PROF_SHM_VERSION;
                DEBUG(3,("Initialised profile area\n"));
        }
 
+       profile_p = &profile_h->stats;
        message_register(MSG_PROFILE, profile_message);
+       message_register(MSG_REQ_PROFILELEVEL, reqprofile_message);
        return True;
 }
-
+#endif /* WITH_PROFILE */