1 /* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License as published by
5    the Free Software Foundation; version 2 of the License.
6 
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11 
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
15 
16 
17 /* Write some debug info */
18 
19 #include "mariadb.h"
20 #include "sql_priv.h"
21 #include "unireg.h"
22 #include "sql_test.h"
23 #include "sql_base.h"
24 #include "sql_show.h" // calc_sum_of_all_status
25 #include "sql_select.h"
26 #include "keycaches.h"
27 #include <hash.h>
28 #include <thr_alarm.h>
29 #if defined(HAVE_MALLINFO) && defined(HAVE_MALLOC_H)
30 #include <malloc.h>
31 #elif defined(HAVE_MALLINFO) && defined(HAVE_SYS_MALLOC_H)
32 #include <sys/malloc.h>
33 #endif
34 
35 #ifdef HAVE_EVENT_SCHEDULER
36 #include "events.h"
37 #endif
38 
39 static const char *lock_descriptions[] =
40 {
41   /* TL_UNLOCK                  */  "No lock",
42   /* TL_READ_DEFAULT            */  NULL,
43   /* TL_READ                    */  "Low priority read lock",
44   /* TL_READ_WITH_SHARED_LOCKS  */  "Shared read lock",
45   /* TL_READ_HIGH_PRIORITY      */  "High priority read lock",
46   /* TL_READ_NO_INSERT          */  "Read lock without concurrent inserts",
47   /* TL_WRITE_ALLOW_WRITE       */  "Write lock that allows other writers",
48   /* TL_WRITE_CONCURRENT_INSERT */  "Concurrent insert lock",
49   /* TL_WRITE_DELAYED           */  "Lock used by delayed insert",
50   /* TL_WRITE_DEFAULT           */  NULL,
51   /* TL_WRITE_LOW_PRIORITY      */  "Low priority write lock",
52   /* TL_WRITE                   */  "High priority write lock",
53   /* TL_WRITE_ONLY              */  "Highest priority write lock"
54 };
55 
56 
57 #ifndef DBUG_OFF
58 
59 void
60 print_where(COND *cond,const char *info, enum_query_type query_type)
61 {
62   char buff[1024];
63   String str(buff,(uint32) sizeof(buff), system_charset_info);
64   str.length(0);
65   str.extra_allocation(1024);
66   if (cond)
67     cond->print(&str, query_type);
68 
69   DBUG_LOCK_FILE;
70   (void) fprintf(DBUG_FILE,"\nWHERE:(%s) %p ", info, cond);
71   (void) fputs(str.c_ptr_safe(),DBUG_FILE);
72   (void) fputc('\n',DBUG_FILE);
73   DBUG_UNLOCK_FILE;
74 }
75 
76 #ifdef EXTRA_DEBUG
77 	/* This is for debugging purposes */
78 static my_bool print_cached_tables_callback(TDC_element *element,
79                                             void *arg __attribute__((unused)))
80 {
81   TABLE *entry;
82 
83   mysql_mutex_lock(&element->LOCK_table_share);
84   All_share_tables_list::Iterator it(element->all_tables);
85   while ((entry= it++))
86   {
87     THD *in_use= entry->in_use;
88     printf("%-14.14s %-32s%6lu%8ld%6d  %s\n",
89            entry->s->db.str, entry->s->table_name.str,
90            (ulong) element->version,
91            in_use ? (long) in_use->thread_id : (long) 0,
92            entry->db_stat ? 1 : 0,
93            in_use ? lock_descriptions[(int)entry->reginfo.lock_type] :
94                     "Not in use");
95   }
96   mysql_mutex_unlock(&element->LOCK_table_share);
97   return FALSE;
98 }
99 
100 
101 static void print_cached_tables(void)
102 {
103   compile_time_assert(TL_WRITE_ONLY+1 == array_elements(lock_descriptions));
104 
105   /* purecov: begin tested */
106   puts("DB             Table                            Version  Thread  Open  Lock");
107 
108   tdc_iterate(0, (my_hash_walk_action) print_cached_tables_callback, NULL, true);
109 
110   printf("\nCurrent refresh version: %ld\n",
111          (long) tdc_refresh_version());
112   fflush(stdout);
113   /* purecov: end */
114   return;
115 }
116 #endif
117 
118 
119 void TEST_filesort(SORT_FIELD *sortorder,uint s_length)
120 {
121   char buff[256],buff2[256];
122   String str(buff,sizeof(buff),system_charset_info);
123   String out(buff2,sizeof(buff2),system_charset_info);
124   const char *sep;
125   DBUG_ENTER("TEST_filesort");
126 
127   out.length(0);
128   for (sep=""; s_length-- ; sortorder++, sep=" ")
129   {
130     out.append(sep);
131     if (sortorder->reverse)
132       out.append('-');
133     if (sortorder->field)
134     {
135       if (sortorder->field->table_name)
136       {
137 	out.append(*sortorder->field->table_name);
138 	out.append('.');
139       }
140       out.append(sortorder->field->field_name.str ?
141                  sortorder->field->field_name.str :
142 		 "tmp_table_column");
143     }
144     else
145     {
146       str.length(0);
147       sortorder->item->print(&str, QT_ORDINARY);
148       out.append(str);
149     }
150   }
151   DBUG_LOCK_FILE;
152   (void) fputs("\nInfo about FILESORT\n",DBUG_FILE);
153   fprintf(DBUG_FILE,"Sortorder: %s\n",out.c_ptr_safe());
154   DBUG_UNLOCK_FILE;
155   DBUG_VOID_RETURN;
156 }
157 
158 
159 void
160 TEST_join(JOIN *join)
161 {
162   uint ref;
163   int i;
164   List_iterator<JOIN_TAB_RANGE> it(join->join_tab_ranges);
165   JOIN_TAB_RANGE *jt_range;
166   DBUG_ENTER("TEST_join");
167 
168   DBUG_LOCK_FILE;
169   (void) fputs("\nInfo about JOIN\n",DBUG_FILE);
170   while ((jt_range= it++))
171   {
172     /*
173       Assemble results of all the calls to full_name() first,
174       in order not to garble the tabular output below.
175     */
176     String ref_key_parts[MAX_TABLES];
177     int tables_in_range= (int)(jt_range->end - jt_range->start);
178     for (i= 0; i < tables_in_range; i++)
179     {
180       JOIN_TAB *tab= jt_range->start + i;
181       for (ref= 0; ref < tab->ref.key_parts; ref++)
182       {
183         ref_key_parts[i].append(tab->ref.items[ref]->full_name());
184         ref_key_parts[i].append("  ");
185       }
186     }
187 
188     for (i= 0; i < tables_in_range; i++)
189     {
190       JOIN_TAB *tab= jt_range->start + i;
191       TABLE *form=tab->table;
192       char key_map_buff[128];
193       fprintf(DBUG_FILE,"%-16.16s  type: %-7s  q_keys: %s  refs: %d  key: %d  len: %d\n",
194 	    form->alias.c_ptr(),
195               join_type_str[tab->type],
196               tab->keys.print(key_map_buff),
197               tab->ref.key_parts,
198               tab->ref.key,
199               tab->ref.key_length);
200       if (tab->select)
201       {
202         char buf[MAX_KEY/8+1];
203         if (tab->use_quick == 2)
204           fprintf(DBUG_FILE,
205                   "                  quick select checked for each record (keys: %s)\n",
206                   tab->select->quick_keys.print(buf));
207         else if (tab->select->quick)
208         {
209           fprintf(DBUG_FILE, "                  quick select used:\n");
210           tab->select->quick->dbug_dump(18, FALSE);
211         }
212         else
213           (void)fputs("                  select used\n",DBUG_FILE);
214       }
215       if (tab->ref.key_parts)
216       {
217         fprintf(DBUG_FILE,
218               "                  refs:  %s\n", ref_key_parts[i].c_ptr_safe());
219       }
220     }
221     (void)fputs("\n",DBUG_FILE);
222   }
223   DBUG_UNLOCK_FILE;
224   DBUG_VOID_RETURN;
225 }
226 
227 
228 #define FT_KEYPART   (MAX_FIELDS+10)
229 
230 static void print_keyuse(KEYUSE *keyuse)
231 {
232   char buff[256];
233   char buf2[64];
234   const char *fieldname;
235   JOIN_TAB *join_tab= keyuse->table->reginfo.join_tab;
236   KEY *key_info= join_tab->get_keyinfo_by_key_no(keyuse->key);
237   String str(buff,(uint32) sizeof(buff), system_charset_info);
238   str.length(0);
239   keyuse->val->print(&str, QT_ORDINARY);
240   str.append('\0');
241   if (keyuse->is_for_hash_join())
242     fieldname= keyuse->table->field[keyuse->keypart]->field_name.str;
243   else if (keyuse->keypart == FT_KEYPART)
244     fieldname= "FT_KEYPART";
245   else
246     fieldname= key_info->key_part[keyuse->keypart].field->field_name.str;
247   ll2str(keyuse->used_tables, buf2, 16, 0);
248   fprintf(DBUG_FILE, "KEYUSE: %s.%s=%s  optimize: %u  used_tables: %s "
249           "ref_table_rows: %lu  keypart_map: %0lx\n",
250           keyuse->table->alias.c_ptr(), fieldname, str.ptr(),
251           (uint) keyuse->optimize, buf2, (ulong) keyuse->ref_table_rows,
252           (ulong) keyuse->keypart_map);
253 }
254 
255 
256 /* purecov: begin inspected */
257 void print_keyuse_array(DYNAMIC_ARRAY *keyuse_array)
258 {
259   DBUG_LOCK_FILE;
260   fprintf(DBUG_FILE, "KEYUSE array (%d elements)\n", keyuse_array->elements);
261   for(uint i=0; i < keyuse_array->elements; i++)
262     print_keyuse((KEYUSE*)dynamic_array_ptr(keyuse_array, i));
263   DBUG_UNLOCK_FILE;
264 }
265 
266 
267 /*
268   Print the current state during query optimization.
269 
270   SYNOPSIS
271     print_plan()
272     join         pointer to the structure providing all context info for
273                  the query
274     read_time    the cost of the best partial plan
275     record_count estimate for the number of records returned by the best
276                  partial plan
277     idx          length of the partial QEP in 'join->positions';
278                  also an index in the array 'join->best_ref';
279     info         comment string to appear above the printout
280 
281   DESCRIPTION
282     This function prints to the log file DBUG_FILE the members of 'join' that
283     are used during query optimization (join->positions, join->best_positions,
284     and join->best_ref) and few other related variables (read_time,
285     record_count).
286     Useful to trace query optimizer functions.
287 
288   RETURN
289     None
290 */
291 
292 void
293 print_plan(JOIN* join, uint idx, double record_count, double read_time,
294            double current_read_time, const char *info)
295 {
296   uint i;
297   POSITION pos;
298   JOIN_TAB *join_table;
299   JOIN_TAB **plan_nodes;
300   TABLE*   table;
301 
302   if (info == 0)
303     info= "";
304 
305   DBUG_LOCK_FILE;
306   if (join->best_read == DBL_MAX)
307   {
308     fprintf(DBUG_FILE,
309             "%s; idx: %u  best: DBL_MAX  atime: %g  itime: %g  count: %g\n",
310             info, idx, current_read_time, read_time, record_count);
311   }
312   else
313   {
314     fprintf(DBUG_FILE,
315             "%s; idx :%u  best: %g  accumulated: %g  increment: %g  count: %g\n",
316             info, idx, join->best_read, current_read_time, read_time,
317             record_count);
318   }
319 
320   /* Print the tables in JOIN->positions */
321   fputs("     POSITIONS: ", DBUG_FILE);
322   for (i= 0; i < idx ; i++)
323   {
324     pos = join->positions[i];
325     table= pos.table->table;
326     if (table)
327       fputs(table->s->table_name.str, DBUG_FILE);
328     fputc(' ', DBUG_FILE);
329   }
330   fputc('\n', DBUG_FILE);
331 
332   /*
333     Print the tables in JOIN->best_positions only if at least one complete plan
334     has been found. An indicator for this is the value of 'join->best_read'.
335   */
336   if (join->best_read < DBL_MAX)
337   {
338     fputs("BEST_POSITIONS: ", DBUG_FILE);
339     for (i= 0; i < idx ; i++)
340     {
341       pos= join->best_positions[i];
342       table= pos.table->table;
343       if (table)
344         fputs(table->s->table_name.str, DBUG_FILE);
345       fputc(' ', DBUG_FILE);
346     }
347   }
348   fputc('\n', DBUG_FILE);
349 
350   /* Print the tables in JOIN->best_ref */
351   fputs("      BEST_REF: ", DBUG_FILE);
352   for (plan_nodes= join->best_ref ; *plan_nodes ; plan_nodes++)
353   {
354     join_table= (*plan_nodes);
355     fputs(join_table->table->s->table_name.str, DBUG_FILE);
356     fprintf(DBUG_FILE, "(%lu,%lu,%lu)",
357             (ulong) join_table->found_records,
358             (ulong) join_table->records,
359             (ulong) join_table->read_time);
360     fputc(' ', DBUG_FILE);
361   }
362   fputc('\n', DBUG_FILE);
363 
364   DBUG_UNLOCK_FILE;
365 }
366 
367 
368 void print_sjm(SJ_MATERIALIZATION_INFO *sjm)
369 {
370   DBUG_LOCK_FILE;
371   fprintf(DBUG_FILE, "\nsemi-join nest{\n");
372   fprintf(DBUG_FILE, "  tables { \n");
373   for (uint i= 0;i < sjm->tables; i++)
374   {
375     fprintf(DBUG_FILE, "    %s%s\n",
376             sjm->positions[i].table->table->alias.c_ptr(),
377             (i == sjm->tables -1)? "": ",");
378   }
379   fprintf(DBUG_FILE, "  }\n");
380   fprintf(DBUG_FILE, "  materialize_cost= %g\n",
381           sjm->materialization_cost.total_cost());
382   fprintf(DBUG_FILE, "  rows= %g\n", sjm->rows);
383   fprintf(DBUG_FILE, "}\n");
384   DBUG_UNLOCK_FILE;
385 }
386 /* purecov: end */
387 
388 /*
389   Debugging help: force List<...>::elem function not be removed as unused.
390 */
391 Item* (List<Item>::*dbug_list_item_elem_ptr)(uint)= &List<Item>::elem;
392 Item_equal* (List<Item_equal>::*dbug_list_item_equal_elem_ptr)(uint)=
393   &List<Item_equal>::elem;
394 TABLE_LIST* (List<TABLE_LIST>::*dbug_list_table_list_elem_ptr)(uint) =
395   &List<TABLE_LIST>::elem;
396 
397 #endif
398 
399 typedef struct st_debug_lock
400 {
401   ulong thread_id;
402   char table_name[FN_REFLEN];
403   bool waiting;
404   const char *lock_text;
405   enum thr_lock_type type;
406 } TABLE_LOCK_INFO;
407 
408 C_MODE_START
409 static int dl_compare(const void *p1, const void *p2)
410 {
411   TABLE_LOCK_INFO *a, *b;
412 
413   a= (TABLE_LOCK_INFO *) p1;
414   b= (TABLE_LOCK_INFO *) p2;
415 
416   if (a->thread_id > b->thread_id)
417     return 1;
418   if (a->thread_id < b->thread_id)
419     return -1;
420   if (a->waiting == b->waiting)
421     return 0;
422   else if (a->waiting)
423     return -1;
424   return 1;
425 }
426 C_MODE_END
427 
428 
429 static void push_locks_into_array(DYNAMIC_ARRAY *ar, THR_LOCK_DATA *data,
430 				  bool wait, const char *text)
431 {
432   if (data)
433   {
434     TABLE *table=(TABLE *)data->debug_print_param;
435     if (table && table->s->tmp_table == NO_TMP_TABLE)
436     {
437       TABLE_LOCK_INFO table_lock_info;
438       table_lock_info.thread_id= (ulong)table->in_use->thread_id;
439       memcpy(table_lock_info.table_name, table->s->table_cache_key.str,
440 	     table->s->table_cache_key.length);
441       table_lock_info.table_name[strlen(table_lock_info.table_name)]='.';
442       table_lock_info.waiting=wait;
443       table_lock_info.lock_text=text;
444       // lock_type is also obtainable from THR_LOCK_DATA
445       table_lock_info.type=table->reginfo.lock_type;
446       (void) push_dynamic(ar,(uchar*) &table_lock_info);
447     }
448   }
449 }
450 
451 
452 /*
453   Regarding MERGE tables:
454 
455   For now, the best option is to use the common TABLE *pointer for all
456   cases;  The drawback is that for MERGE tables we will see many locks
457   for the merge tables even if some of them are for individual tables.
458 
459   The way to solve this is to add to 'THR_LOCK' structure a pointer to
460   the filename and use this when printing the data.
461   (We can for now ignore this and just print the same name for all merge
462   table parts;  Please add the above as a comment to the display_lock
463   function so that we can easily add this if we ever need this.
464 */
465 
466 static void display_table_locks(void)
467 {
468   LIST *list;
469   void *saved_base;
470   DYNAMIC_ARRAY saved_table_locks;
471 
472   (void) my_init_dynamic_array(&saved_table_locks,sizeof(TABLE_LOCK_INFO),
473                                tc_records() + 20, 50, MYF(0));
474   mysql_mutex_lock(&THR_LOCK_lock);
475   for (list= thr_lock_thread_list; list; list= list_rest(list))
476   {
477     THR_LOCK *lock=(THR_LOCK*) list->data;
478 
479     mysql_mutex_lock(&lock->mutex);
480     push_locks_into_array(&saved_table_locks, lock->write.data, FALSE,
481 			  "Locked - write");
482     push_locks_into_array(&saved_table_locks, lock->write_wait.data, TRUE,
483 			  "Waiting - write");
484     push_locks_into_array(&saved_table_locks, lock->read.data, FALSE,
485 			  "Locked - read");
486     push_locks_into_array(&saved_table_locks, lock->read_wait.data, TRUE,
487 			  "Waiting - read");
488     mysql_mutex_unlock(&lock->mutex);
489   }
490   mysql_mutex_unlock(&THR_LOCK_lock);
491 
492   if (!saved_table_locks.elements)
493     goto end;
494 
495   saved_base= dynamic_element(&saved_table_locks, 0, TABLE_LOCK_INFO *);
496   my_qsort(saved_base, saved_table_locks.elements, sizeof(TABLE_LOCK_INFO),
497            dl_compare);
498   freeze_size(&saved_table_locks);
499 
500   puts("\nThread database.table_name          Locked/Waiting        Lock_type\n");
501 
502   unsigned int i;
503   for (i=0 ; i < saved_table_locks.elements ; i++)
504   {
505     TABLE_LOCK_INFO *dl_ptr=dynamic_element(&saved_table_locks,i,TABLE_LOCK_INFO*);
506     printf("%-8ld%-28.28s%-22s%s\n",
507 	   dl_ptr->thread_id,dl_ptr->table_name,dl_ptr->lock_text,lock_descriptions[(int)dl_ptr->type]);
508   }
509   puts("\n\n");
510 end:
511   delete_dynamic(&saved_table_locks);
512 }
513 
514 C_MODE_START
515 static int print_key_cache_status(const char *name, KEY_CACHE *key_cache,
516                                   void *unused __attribute__((unused)))
517 {
518   char llbuff1[22];
519   char llbuff2[22];
520   char llbuff3[22];
521   char llbuff4[22];
522 
523   if (!key_cache->key_cache_inited)
524   {
525     printf("%s: Not in use\n", name);
526   }
527   else
528   {
529     KEY_CACHE_STATISTICS stats;
530     get_key_cache_statistics(key_cache, 0, &stats);
531 
532     printf("%s\n\
533 Buffer_size:    %10lu\n\
534 Block_size:     %10lu\n\
535 Division_limit: %10lu\n\
536 Age_threshold:  %10lu\n\
537 Partitions:     %10lu\n\
538 blocks used:    %10lu\n\
539 not flushed:    %10lu\n\
540 w_requests:     %10s\n\
541 writes:         %10s\n\
542 r_requests:     %10s\n\
543 reads:          %10s\n\n",
544 	   name,
545 	   (ulong)key_cache->param_buff_size,
546            (ulong)key_cache->param_block_size,
547 	   (ulong)key_cache->param_division_limit,
548            (ulong)key_cache->param_age_threshold,
549            (ulong)key_cache->param_partitions,
550 	   (ulong)stats.blocks_used,
551            (ulong)stats.blocks_changed,
552 	   llstr(stats.write_requests,llbuff1),
553            llstr(stats.writes,llbuff2),
554 	   llstr(stats.read_requests,llbuff3),
555            llstr(stats.reads,llbuff4));
556   }
557   return 0;
558 }
559 C_MODE_END
560 
561 
562 void mysql_print_status()
563 {
564   char current_dir[FN_REFLEN];
565   STATUS_VAR tmp;
566   uint count;
567 
568   tmp= global_status_var;
569   count= calc_sum_of_all_status(&tmp);
570   printf("\nStatus information:\n\n");
571   (void) my_getwd(current_dir, sizeof(current_dir),MYF(0));
572   printf("Current dir: %s\n", current_dir);
573   printf("Running threads: %d  Cached threads: %lu  Stack size: %ld\n",
574          count, cached_thread_count,
575 	 (long) my_thread_stack_size);
576 #ifdef EXTRA_DEBUG
577   thr_print_locks();				// Write some debug info
578   print_cached_tables();
579 #endif
580   /* Print key cache status */
581   puts("\nKey caches:");
582   process_key_caches(print_key_cache_status, 0);
583   printf("\nhandler status:\n\
584 read_key:   %10lu\n\
585 read_next:  %10lu\n\
586 read_rnd    %10lu\n\
587 read_first: %10lu\n\
588 write:      %10lu\n\
589 delete      %10lu\n\
590 update:     %10lu\n",
591 	 tmp.ha_read_key_count,
592 	 tmp.ha_read_next_count,
593 	 tmp.ha_read_rnd_count,
594 	 tmp.ha_read_first_count,
595 	 tmp.ha_write_count,
596 	 tmp.ha_delete_count,
597 	 tmp.ha_update_count);
598   printf("\nTable status:\n\
599 Opened tables: %10lu\n\
600 Open tables:   %10u\n\
601 Open files:    %10u\n\
602 Open streams:  %10lu\n",
603 	 tmp.opened_tables,
604 	 tc_records(),
605 	 my_file_opened,
606 	 my_stream_opened);
607 
608 #ifndef DONT_USE_THR_ALARM
609   ALARM_INFO alarm_info;
610   thr_alarm_info(&alarm_info);
611   printf("\nAlarm status:\n\
612 Active alarms:   %u\n\
613 Max used alarms: %u\n\
614 Next alarm time: %lu\n",
615 	 alarm_info.active_alarms,
616 	 alarm_info.max_used_alarms,
617 	(ulong)alarm_info.next_alarm_time);
618 #endif
619   display_table_locks();
620 #if defined(HAVE_MALLINFO2)
621   struct mallinfo2 info = mallinfo2();
622 #elif defined(HAVE_MALLINFO)
623   struct mallinfo info= mallinfo();
624 #endif
625 #if defined(HAVE_MALLINFO) || defined(HAVE_MALLINFO2)
626   char llbuff[10][22];
627   printf("\nMemory status:\n\
628 Non-mmapped space allocated from system: %s\n\
629 Number of free chunks:                   %lu\n\
630 Number of fastbin blocks:                %lu\n\
631 Number of mmapped regions:               %lu\n\
632 Space in mmapped regions:                %s\n\
633 Maximum total allocated space:           %s\n\
634 Space available in freed fastbin blocks: %s\n\
635 Total allocated space:                   %s\n\
636 Total free space:                        %s\n\
637 Top-most, releasable space:              %s\n\
638 Estimated memory (with thread stack):    %s\n\
639 Global memory allocated by server:       %s\n\
640 Memory allocated by threads:             %s\n",
641 	 llstr(info.arena,   llbuff[0]),
642 	 (ulong) info.ordblks,
643 	 (ulong) info.smblks,
644 	 (ulong) info.hblks,
645 	 llstr(info.hblkhd,   llbuff[1]),
646 	 llstr(info.usmblks,  llbuff[2]),
647 	 llstr(info.fsmblks,  llbuff[3]),
648 	 llstr(info.uordblks, llbuff[4]),
649 	 llstr(info.fordblks, llbuff[5]),
650 	 llstr(info.keepcost, llbuff[6]),
651 	 llstr((count + cached_thread_count)* my_thread_stack_size + info.hblkhd + info.arena, llbuff[7]),
652          llstr(tmp.global_memory_used, llbuff[8]),
653          llstr(tmp.local_memory_used, llbuff[9]));
654 
655 #endif
656 
657 #ifdef HAVE_EVENT_SCHEDULER
658   Events::dump_internal_status();
659 #endif
660   puts("");
661   fflush(stdout);
662 }
663