Print this page
update to acpica-unix2-20140114
update to acpica-unix2-20131115
acpica-unix2-20130823
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/acpica/namespace/nsalloc.c
+++ new/usr/src/common/acpica/components/namespace/nsalloc.c
1 1 /*******************************************************************************
2 2 *
3 3 * Module Name: nsalloc - Namespace allocation and deletion utilities
4 4 *
5 5 ******************************************************************************/
6 6
7 7 /*
8 - * Copyright (C) 2000 - 2011, Intel Corp.
8 + * Copyright (C) 2000 - 2014, Intel Corp.
9 9 * All rights reserved.
10 10 *
11 11 * Redistribution and use in source and binary forms, with or without
12 12 * modification, are permitted provided that the following conditions
13 13 * are met:
14 14 * 1. Redistributions of source code must retain the above copyright
15 15 * notice, this list of conditions, and the following disclaimer,
16 16 * without modification.
17 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 18 * substantially similar to the "NO WARRANTY" disclaimer below
19 19 * ("Disclaimer") and any redistribution must be conditioned upon
20 20 * including a substantially similar Disclaimer requirement for further
21 21 * binary redistribution.
22 22 * 3. Neither the names of the above-listed copyright holders nor the names
23 23 * of any contributors may be used to endorse or promote products derived
24 24 * from this software without specific prior written permission.
25 25 *
26 26 * Alternatively, this software may be distributed under the terms of the
27 27 * GNU General Public License ("GPL") version 2 as published by the Free
28 28 * Software Foundation.
29 29 *
30 30 * NO WARRANTY
31 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 41 * POSSIBILITY OF SUCH DAMAGES.
42 42 */
43 43
44 44
45 45 #define __NSALLOC_C__
46 46
47 47 #include "acpi.h"
48 48 #include "accommon.h"
49 49 #include "acnamesp.h"
50 50
51 51
52 52 #define _COMPONENT ACPI_NAMESPACE
53 53 ACPI_MODULE_NAME ("nsalloc")
54 54
55 55
56 56 /*******************************************************************************
57 57 *
58 58 * FUNCTION: AcpiNsCreateNode
59 59 *
60 60 * PARAMETERS: Name - Name of the new node (4 char ACPI name)
61 61 *
62 62 * RETURN: New namespace node (Null on failure)
63 63 *
64 64 * DESCRIPTION: Create a namespace node
65 65 *
66 66 ******************************************************************************/
67 67
68 68 ACPI_NAMESPACE_NODE *
69 69 AcpiNsCreateNode (
70 70 UINT32 Name)
71 71 {
72 72 ACPI_NAMESPACE_NODE *Node;
73 73 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
74 74 UINT32 Temp;
75 75 #endif
76 76
77 77
78 78 ACPI_FUNCTION_TRACE (NsCreateNode);
79 79
80 80
81 81 Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache);
82 82 if (!Node)
83 83 {
84 84 return_PTR (NULL);
85 85 }
86 86
87 87 ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++);
88 88
89 89 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
90 90 Temp = AcpiGbl_NsNodeList->TotalAllocated -
91 91 AcpiGbl_NsNodeList->TotalFreed;
92 92 if (Temp > AcpiGbl_NsNodeList->MaxOccupied)
93 93 {
94 94 AcpiGbl_NsNodeList->MaxOccupied = Temp;
95 95 }
96 96 #endif
97 97
98 98 Node->Name.Integer = Name;
99 99 ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
100 100 return_PTR (Node);
101 101 }
102 102
103 103
104 104 /*******************************************************************************
105 105 *
106 106 * FUNCTION: AcpiNsDeleteNode
107 107 *
108 108 * PARAMETERS: Node - Node to be deleted
109 109 *
110 110 * RETURN: None
111 111 *
112 112 * DESCRIPTION: Delete a namespace node. All node deletions must come through
113 113 * here. Detaches any attached objects, including any attached
↓ open down ↓ |
95 lines elided |
↑ open up ↑ |
114 114 * data. If a handler is associated with attached data, it is
115 115 * invoked before the node is deleted.
116 116 *
117 117 ******************************************************************************/
118 118
119 119 void
120 120 AcpiNsDeleteNode (
121 121 ACPI_NAMESPACE_NODE *Node)
122 122 {
123 123 ACPI_OPERAND_OBJECT *ObjDesc;
124 + ACPI_OPERAND_OBJECT *NextDesc;
124 125
125 126
126 127 ACPI_FUNCTION_NAME (NsDeleteNode);
127 128
128 129
129 130 /* Detach an object if there is one */
130 131
131 132 AcpiNsDetachObject (Node);
132 133
133 134 /*
134 - * Delete an attached data object if present (an object that was created
135 - * and attached via AcpiAttachData). Note: After any normal object is
136 - * detached above, the only possible remaining object is a data object.
135 + * Delete an attached data object list if present (objects that were
136 + * attached via AcpiAttachData). Note: After any normal object is
137 + * detached above, the only possible remaining object(s) are data
138 + * objects, in a linked list.
137 139 */
138 140 ObjDesc = Node->Object;
139 - if (ObjDesc &&
141 + while (ObjDesc &&
140 142 (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
141 143 {
142 144 /* Invoke the attached data deletion handler if present */
143 145
144 146 if (ObjDesc->Data.Handler)
145 147 {
146 148 ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer);
147 149 }
148 150
151 + NextDesc = ObjDesc->Common.NextObject;
149 152 AcpiUtRemoveReference (ObjDesc);
153 + ObjDesc = NextDesc;
150 154 }
151 155
156 + /* Special case for the statically allocated root node */
157 +
158 + if (Node == AcpiGbl_RootNode)
159 + {
160 + return;
161 + }
162 +
152 163 /* Now we can delete the node */
153 164
154 165 (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node);
155 166
156 167 ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
157 168 ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
158 169 Node, AcpiGbl_CurrentNodeCount));
159 170 }
160 171
161 172
162 173 /*******************************************************************************
163 174 *
164 175 * FUNCTION: AcpiNsRemoveNode
165 176 *
166 177 * PARAMETERS: Node - Node to be removed/deleted
167 178 *
168 179 * RETURN: None
169 180 *
170 181 * DESCRIPTION: Remove (unlink) and delete a namespace node
171 182 *
172 183 ******************************************************************************/
173 184
174 185 void
175 186 AcpiNsRemoveNode (
176 187 ACPI_NAMESPACE_NODE *Node)
177 188 {
178 189 ACPI_NAMESPACE_NODE *ParentNode;
179 190 ACPI_NAMESPACE_NODE *PrevNode;
180 191 ACPI_NAMESPACE_NODE *NextNode;
181 192
182 193
183 194 ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node);
184 195
185 196
186 197 ParentNode = Node->Parent;
187 198
188 199 PrevNode = NULL;
189 200 NextNode = ParentNode->Child;
190 201
191 202 /* Find the node that is the previous peer in the parent's child list */
192 203
193 204 while (NextNode != Node)
194 205 {
195 206 PrevNode = NextNode;
196 207 NextNode = NextNode->Peer;
197 208 }
198 209
199 210 if (PrevNode)
200 211 {
201 212 /* Node is not first child, unlink it */
202 213
203 214 PrevNode->Peer = Node->Peer;
204 215 }
205 216 else
206 217 {
207 218 /*
208 219 * Node is first child (has no previous peer).
209 220 * Link peer list to parent
210 221 */
211 222 ParentNode->Child = Node->Peer;
212 223 }
213 224
214 225 /* Delete the node and any attached objects */
215 226
216 227 AcpiNsDeleteNode (Node);
217 228 return_VOID;
218 229 }
219 230
220 231
221 232 /*******************************************************************************
222 233 *
223 234 * FUNCTION: AcpiNsInstallNode
224 235 *
225 236 * PARAMETERS: WalkState - Current state of the walk
226 237 * ParentNode - The parent of the new Node
227 238 * Node - The new Node to install
228 239 * Type - ACPI object type of the new Node
229 240 *
230 241 * RETURN: None
231 242 *
232 243 * DESCRIPTION: Initialize a new namespace node and install it amongst
233 244 * its peers.
234 245 *
235 246 * Note: Current namespace lookup is linear search. This appears
236 247 * to be sufficient as namespace searches consume only a small
237 248 * fraction of the execution time of the ACPI subsystem.
238 249 *
239 250 ******************************************************************************/
240 251
241 252 void
242 253 AcpiNsInstallNode (
243 254 ACPI_WALK_STATE *WalkState,
244 255 ACPI_NAMESPACE_NODE *ParentNode, /* Parent */
245 256 ACPI_NAMESPACE_NODE *Node, /* New Child*/
246 257 ACPI_OBJECT_TYPE Type)
247 258 {
248 259 ACPI_OWNER_ID OwnerId = 0;
249 260 ACPI_NAMESPACE_NODE *ChildNode;
250 261
251 262
252 263 ACPI_FUNCTION_TRACE (NsInstallNode);
253 264
254 265
255 266 if (WalkState)
256 267 {
257 268 /*
258 269 * Get the owner ID from the Walk state. The owner ID is used to
259 270 * track table deletion and deletion of objects created by methods.
260 271 */
261 272 OwnerId = WalkState->OwnerId;
262 273
263 274 if ((WalkState->MethodDesc) &&
264 275 (ParentNode != WalkState->MethodNode))
265 276 {
266 277 /*
267 278 * A method is creating a new node that is not a child of the
268 279 * method (it is non-local). Mark the executing method as having
269 280 * modified the namespace. This is used for cleanup when the
270 281 * method exits.
271 282 */
272 283 WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_MODIFIED_NAMESPACE;
273 284 }
274 285 }
275 286
276 287 /* Link the new entry into the parent and existing children */
277 288
278 289 Node->Peer = NULL;
279 290 Node->Parent = ParentNode;
280 291 ChildNode = ParentNode->Child;
281 292
282 293 if (!ChildNode)
283 294 {
284 295 ParentNode->Child = Node;
285 296 }
286 297 else
287 298 {
288 299 /* Add node to the end of the peer list */
289 300
290 301 while (ChildNode->Peer)
291 302 {
292 303 ChildNode = ChildNode->Peer;
293 304 }
294 305
295 306 ChildNode->Peer = Node;
296 307 }
297 308
298 309 /* Init the new entry */
299 310
300 311 Node->OwnerId = OwnerId;
301 312 Node->Type = (UINT8) Type;
302 313
303 314 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
304 315 "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
305 316 AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
306 317 AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
307 318 ParentNode));
308 319
309 320 return_VOID;
310 321 }
311 322
312 323
313 324 /*******************************************************************************
314 325 *
315 326 * FUNCTION: AcpiNsDeleteChildren
316 327 *
317 328 * PARAMETERS: ParentNode - Delete this objects children
318 329 *
319 330 * RETURN: None.
320 331 *
321 332 * DESCRIPTION: Delete all children of the parent object. In other words,
322 333 * deletes a "scope".
323 334 *
324 335 ******************************************************************************/
325 336
326 337 void
327 338 AcpiNsDeleteChildren (
328 339 ACPI_NAMESPACE_NODE *ParentNode)
329 340 {
330 341 ACPI_NAMESPACE_NODE *NextNode;
331 342 ACPI_NAMESPACE_NODE *NodeToDelete;
332 343
333 344
334 345 ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode);
335 346
336 347
337 348 if (!ParentNode)
338 349 {
339 350 return_VOID;
340 351 }
341 352
342 353 /* Deallocate all children at this level */
343 354
344 355 NextNode = ParentNode->Child;
345 356 while (NextNode)
346 357 {
347 358 /* Grandchildren should have all been deleted already */
348 359
349 360 if (NextNode->Child)
350 361 {
351 362 ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p",
352 363 ParentNode, NextNode));
353 364 }
354 365
355 366 /*
356 367 * Delete this child node and move on to the next child in the list.
357 368 * No need to unlink the node since we are deleting the entire branch.
358 369 */
359 370 NodeToDelete = NextNode;
360 371 NextNode = NextNode->Peer;
361 372 AcpiNsDeleteNode (NodeToDelete);
362 373 };
363 374
364 375 /* Clear the parent's child pointer */
365 376
366 377 ParentNode->Child = NULL;
367 378 return_VOID;
368 379 }
↓ open down ↓ |
207 lines elided |
↑ open up ↑ |
369 380
370 381
371 382 /*******************************************************************************
372 383 *
373 384 * FUNCTION: AcpiNsDeleteNamespaceSubtree
374 385 *
375 386 * PARAMETERS: ParentNode - Root of the subtree to be deleted
376 387 *
377 388 * RETURN: None.
378 389 *
379 - * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
390 + * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
380 391 * stored within the subtree.
381 392 *
382 393 ******************************************************************************/
383 394
384 395 void
385 396 AcpiNsDeleteNamespaceSubtree (
386 397 ACPI_NAMESPACE_NODE *ParentNode)
387 398 {
388 399 ACPI_NAMESPACE_NODE *ChildNode = NULL;
389 400 UINT32 Level = 1;
390 401 ACPI_STATUS Status;
391 402
392 403
393 404 ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);
394 405
395 406
396 407 if (!ParentNode)
397 408 {
398 409 return_VOID;
399 410 }
400 411
401 412 /* Lock namespace for possible update */
402 413
403 414 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
404 415 if (ACPI_FAILURE (Status))
405 416 {
406 417 return_VOID;
407 418 }
408 419
409 420 /*
410 421 * Traverse the tree of objects until we bubble back up
411 422 * to where we started.
412 423 */
413 424 while (Level > 0)
414 425 {
415 426 /* Get the next node in this scope (NULL if none) */
416 427
417 428 ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
418 429 if (ChildNode)
419 430 {
420 431 /* Found a child node - detach any attached object */
421 432
422 433 AcpiNsDetachObject (ChildNode);
423 434
424 435 /* Check if this node has any children */
425 436
426 437 if (ChildNode->Child)
427 438 {
428 439 /*
429 440 * There is at least one child of this node,
430 441 * visit the node
431 442 */
432 443 Level++;
433 444 ParentNode = ChildNode;
434 445 ChildNode = NULL;
435 446 }
436 447 }
437 448 else
438 449 {
439 450 /*
440 451 * No more children of this parent node.
441 452 * Move up to the grandparent.
442 453 */
443 454 Level--;
444 455
445 456 /*
446 457 * Now delete all of the children of this parent
447 458 * all at the same time.
448 459 */
449 460 AcpiNsDeleteChildren (ParentNode);
450 461
451 462 /* New "last child" is this parent node */
452 463
453 464 ChildNode = ParentNode;
454 465
455 466 /* Move up the tree to the grandparent */
456 467
457 468 ParentNode = ParentNode->Parent;
458 469 }
459 470 }
460 471
461 472 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
462 473 return_VOID;
463 474 }
464 475
↓ open down ↓ |
75 lines elided |
↑ open up ↑ |
465 476
466 477 /*******************************************************************************
467 478 *
468 479 * FUNCTION: AcpiNsDeleteNamespaceByOwner
469 480 *
470 481 * PARAMETERS: OwnerId - All nodes with this owner will be deleted
471 482 *
472 483 * RETURN: Status
473 484 *
474 485 * DESCRIPTION: Delete entries within the namespace that are owned by a
475 - * specific ID. Used to delete entire ACPI tables. All
486 + * specific ID. Used to delete entire ACPI tables. All
476 487 * reference counts are updated.
477 488 *
478 489 * MUTEX: Locks namespace during deletion walk.
479 490 *
480 491 ******************************************************************************/
481 492
482 493 void
483 494 AcpiNsDeleteNamespaceByOwner (
484 495 ACPI_OWNER_ID OwnerId)
485 496 {
486 497 ACPI_NAMESPACE_NODE *ChildNode;
487 498 ACPI_NAMESPACE_NODE *DeletionNode;
488 499 ACPI_NAMESPACE_NODE *ParentNode;
489 500 UINT32 Level;
490 501 ACPI_STATUS Status;
491 502
492 503
493 504 ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId);
494 505
495 506
496 507 if (OwnerId == 0)
497 508 {
498 509 return_VOID;
499 510 }
500 511
501 512 /* Lock namespace for possible update */
502 513
503 514 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
504 515 if (ACPI_FAILURE (Status))
505 516 {
506 517 return_VOID;
507 518 }
508 519
509 520 DeletionNode = NULL;
510 521 ParentNode = AcpiGbl_RootNode;
511 522 ChildNode = NULL;
512 523 Level = 1;
513 524
514 525 /*
515 526 * Traverse the tree of nodes until we bubble back up
516 527 * to where we started.
517 528 */
518 529 while (Level > 0)
519 530 {
520 531 /*
521 532 * Get the next child of this parent node. When ChildNode is NULL,
522 533 * the first child of the parent is returned
523 534 */
524 535 ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
525 536
526 537 if (DeletionNode)
527 538 {
528 539 AcpiNsDeleteChildren (DeletionNode);
529 540 AcpiNsRemoveNode (DeletionNode);
530 541 DeletionNode = NULL;
531 542 }
532 543
533 544 if (ChildNode)
534 545 {
535 546 if (ChildNode->OwnerId == OwnerId)
536 547 {
537 548 /* Found a matching child node - detach any attached object */
538 549
539 550 AcpiNsDetachObject (ChildNode);
540 551 }
541 552
542 553 /* Check if this node has any children */
543 554
544 555 if (ChildNode->Child)
545 556 {
546 557 /*
547 558 * There is at least one child of this node,
548 559 * visit the node
549 560 */
550 561 Level++;
551 562 ParentNode = ChildNode;
552 563 ChildNode = NULL;
553 564 }
554 565 else if (ChildNode->OwnerId == OwnerId)
555 566 {
556 567 DeletionNode = ChildNode;
557 568 }
558 569 }
559 570 else
560 571 {
561 572 /*
562 573 * No more children of this parent node.
563 574 * Move up to the grandparent.
564 575 */
565 576 Level--;
566 577 if (Level != 0)
567 578 {
568 579 if (ParentNode->OwnerId == OwnerId)
569 580 {
570 581 DeletionNode = ParentNode;
571 582 }
572 583 }
573 584
574 585 /* New "last child" is this parent node */
575 586
576 587 ChildNode = ParentNode;
↓ open down ↓ |
91 lines elided |
↑ open up ↑ |
577 588
578 589 /* Move up the tree to the grandparent */
579 590
580 591 ParentNode = ParentNode->Parent;
581 592 }
582 593 }
583 594
584 595 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
585 596 return_VOID;
586 597 }
587 -
588 -
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX