Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Jun 2006 05:27:34 GMT
From:      John Birrell <jb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 99798 for review
Message-ID:  <200606220527.k5M5RYgM007434@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=99798

Change 99798 by jb@jb_freebsd2 on 2006/06/22 05:26:53

	Load the DTrace modules if the dtrace_load environment variable
	is set. This still belongs in 4th because the DTrace providers
	should be readily customisable. I just don't know how to do that.
	
	When booting with DTrace enabled, load the anonymous enablings
	from '/boot/dtrace.dof' in lieu of the driver configuration file
	system that Solaris has.
	
	The DOF strings are likely to be longer than the 255 character
	maximum that FreeBSD's forth implementation supports, so it is
	easier to do it in C and re-allocate the input buffer size if
	a larger string is required.
	
	Once the DOF strings read, add them to the kernel environment
	from where the 'dtrace' module can access them in the usual
	getenv() way.

Affected files ...

.. //depot/projects/dtrace/src/sys/boot/common/boot.c#2 edit

Differences ...

==== //depot/projects/dtrace/src/sys/boot/common/boot.c#2 (text+ko) ====

@@ -52,6 +52,8 @@
 static int
 command_boot(int argc, char *argv[])
 {
+    int	error;
+    int	fd;
     struct preloaded_file	*fp;
 
     /*
@@ -102,6 +104,119 @@
     if (archsw.arch_autoload() != 0)
 	return(CMD_ERROR);
 
+    /* Check if DTrace is to be loaded prior to boot. */
+    if (getenv("dtrace_load")) {
+	/*
+	 * Load the DTrace modules. This would be better done
+	 * in 4th so that extra providers can be added easily.
+	 */
+	error = mod_load("cyclic", NULL, 0, NULL);
+	if (error != 0)
+	    printf("cyclic autoload failed - %s\n", strerror(error));
+	error = mod_load("dtrace", NULL, 0, NULL);
+	if (error != 0)
+	    printf("dtrace autoload failed - %s\n", strerror(error));
+	error = mod_load("profile", NULL, 0, NULL);
+	if (error != 0)
+	    printf("profile autoload failed - %s\n", strerror(error));
+	error = mod_load("systrace", NULL, 0, NULL);
+	if (error != 0)
+	    printf("systrace autoload failed - %s\n", strerror(error));
+	error = mod_load("fbt", NULL, 0, NULL);
+	if (error != 0)
+	    printf("fbt autoload failed - %s\n", strerror(error));
+	error = mod_load("sdt", NULL, 0, NULL);
+	if (error != 0)
+	    printf("sdt autoload failed - %s\n", strerror(error));
+
+	/*
+	 * Open the DTrace DOF file if it exists. Don't worry if
+	 * it doesn't.
+	 */
+    	if ((fd = open("/boot/dtrace.dof", O_RDONLY)) >= 0) {
+		char *p;		/* Temporary pointer. */
+		char *p_buf;		/* Ptr to the read buffer. */
+		int n;			/* Number of bytes in string. */
+		size_t n_buf;		/* Number of characters buffered. */
+		size_t s_buf = 4096;	/* Size of the read buffer. */
+
+		/*
+		 * Allocate memory for the initial DOF buffer. This
+		 * will be re-allocated if necessary.
+		 */
+		if ((p_buf = malloc(s_buf)) != NULL) {
+			/*
+			 * Enter a loop to read each line in the DOF
+			 * file and add it to the environment.
+			 */
+			do {
+				/* Start each line with an empty buffer. */
+				n_buf = 0;
+
+				/*
+				 * Enter a loop to read the string in the
+				 * current line, re-allocating the input 
+				 * buffer if it is too small.
+				 */
+				while ((n = fgetstr(p_buf + n_buf, s_buf - n_buf,
+				    fd)) > 0 && n == s_buf - n_buf - 1 &&
+				    p_buf[s_buf - 2] != '\n') {
+					/*
+					 * Update the number of characters
+					 * buffered.
+					 */
+					n_buf += n;
+
+					/* Double the buffer size. */
+					s_buf *= 2;
+
+					/* Re-allocate the buffer. */
+					if ((p = realloc(p_buf, s_buf)) == NULL) {
+						/*
+						 * Can't re-allocate memory, so
+						 * just give up.
+						 */
+						n = 0;
+						n_buf = 0;
+						break;
+					}
+
+					/* Use the newly re-allocated buffer. */
+					p_buf = p;
+				}
+
+				/* Update the number of characters buffered. */
+				if (n > 0)
+					n_buf += n;
+
+				/*
+				 * If there are characters buffered, add the
+				 * input line to the environment.
+				 */
+				if (n_buf > 0 && (p = strchr(p_buf, '=')) != NULL) {
+					/* Zero terminate the name. */
+					*p = '\0';
+
+					/* Point to the value. */
+					p++;
+
+					/* Set the environment variable. */
+					setenv(p_buf, p, 1);
+				}
+
+			/*
+			 * Keep looping until there are no more lines in 
+			 * the file.
+			 */
+			} while (n > 0 && n_buf != 0);
+
+			free(p_buf);
+		}
+
+		close(fd);
+	}
+    }
+
     /* Call the exec handler from the loader matching the kernel */
     file_formats[fp->f_loader]->l_exec(fp);
     return(CMD_ERROR);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200606220527.k5M5RYgM007434>