Print this page
11553 Want pluggable TCP congestion control algorithms
Portions contributed by: Cody Peter Mello <cody.mello@joyent.com>
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Robert Mustacchi <robert.mustacchi@joyent.com>
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/sparc/Makefile.sparc
+++ new/usr/src/uts/sparc/Makefile.sparc
1 1 #
2 2 # CDDL HEADER START
3 3 #
4 4 # The contents of this file are subject to the terms of the
5 5 # Common Development and Distribution License (the "License").
6 6 # You may not use this file except in compliance with the License.
7 7 #
8 8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 # or http://www.opensolaris.org/os/licensing.
10 10 # See the License for the specific language governing permissions
11 11 # and limitations under the License.
12 12 #
13 13 # When distributing Covered Code, include this CDDL HEADER in each
14 14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 # If applicable, add the following below this CDDL HEADER, with the
16 16 # fields enclosed by brackets "[]" replaced with your own identifying
17 17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 18 #
19 19 # CDDL HEADER END
20 20 #
21 21
22 22 #
23 23 # Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 # Copyright (c) 2013 Andrew Stormont. All rights reserved.
25 +# Copyright (c) 2015, 2017 by Delphix. All rights reserved.
25 26 # Copyright 2019 Joyent, Inc.
26 27 # Copyright 2016 Gary Mills
27 28 # Copyright 2016 Nexenta Systems, Inc.
28 29 # Copyright 2019 RackTop Systems
29 30 #
30 31
31 32 #
32 33 # This makefile contains the common definitions for all sparc
33 34 # implementation architecture independent modules.
34 35 #
35 36
36 37 #
37 38 # Define supported builds
38 39 #
39 40 DEF_BUILDS = $(DEF_BUILDS64)
40 41 ALL_BUILDS = $(ALL_BUILDS64)
41 42
42 43 #
43 44 # Everybody needs to know how to build modstubs.o and to locate unix.o.
44 45 # Note that unix.o must currently be selected from among the possible
45 46 # "implementation architectures". Note further, that unix.o is only
46 47 # used as an optional error check for undefines so (theoretically)
47 48 # any "implementation architectures" could be used. We choose sun4u
48 49 # because it is the reference port.
49 50 #
50 51 UNIX_DIR = $(UTSBASE)/sun4u/unix
51 52 GENLIB_DIR = $(UTSBASE)/sun4u/genunix
52 53 IPDRV_DIR = $(UTSBASE)/sparc/ip
53 54 MODSTUBS_DIR = $(UNIX_DIR)
54 55 DSF_DIR = $(UNIX_DIR)
55 56 LINTS_DIR = $(OBJS_DIR)
56 57 LINT_LIB_DIR = $(UTSBASE)/sparc/lint-libs/$(OBJS_DIR)
57 58
58 59 UNIX_O = $(UNIX_DIR)/$(OBJS_DIR)/unix.o
59 60 MODSTUBS_O = $(MODSTUBS_DIR)/$(OBJS_DIR)/modstubs.o
60 61 GENLIB = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR)/libgenunix.so
61 62
62 63 LINT_LIB_32 = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR)/llib-lunix.ln
63 64 GEN_LINT_LIB_32 = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR)/llib-lgenunix.ln
64 65
65 66 LINT_LIB_64 = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR)/llib-lunix.ln
66 67 GEN_LINT_LIB_64 = $(UTSBASE)/sun4u/lint-libs/$(OBJS_DIR)/llib-lgenunix.ln
67 68
68 69 LINT_LIB = $(LINT_LIB_$(CLASS))
69 70 GEN_LINT_LIB = $(GEN_LINT_LIB_$(CLASS))
70 71
71 72 LINT32_DIRS = $(LINT32_BUILDS:%=$(UTSBASE)/sparc/lint-libs/%)
72 73 LINT32_FILES = $(LINT32_DIRS:%=%/llib-l$(MODULE).ln)
73 74
74 75 LINT64_DIRS = $(LINT64_BUILDS:%=$(UTSBASE)/sparc/lint-libs/%)
75 76 LINT64_FILES = $(LINT64_DIRS:%=%/llib-l$(MODULE).ln)
76 77
77 78 #
78 79 # Include the makefiles which define build rule templates, the
79 80 # collection of files per module, and a few specific flags. Note
80 81 # that order is significant, just as with an include path. The
81 82 # first build rule template which matches the files name will be
82 83 # used. By including these in order from most machine dependent
83 84 # to most machine independent, we allow a machine dependent file
84 85 # to be used in preference over a machine independent version
85 86 # (Such as a machine specific optimization, which preserves the
86 87 # interfaces.)
87 88 #
88 89 include $(UTSBASE)/sparc/Makefile.files
89 90 include $(UTSBASE)/sparc/v9/Makefile.files
90 91 include $(UTSBASE)/sun/Makefile.files
91 92 include $(UTSBASE)/common/Makefile.files
92 93
93 94 #
94 95 # ----- TRANSITIONAL SECTION --------------------------------------------------
95 96 #
96 97
97 98 #
98 99 # Not everything which *should* be a module is a module yet. The
99 100 # following is a list of such objects which are currently part of
100 101 # genunix but which might someday become kmods. This must be
101 102 # defined before we include Makefile.uts, or else genunix's build
102 103 # won't be as parallel as we might like.
103 104 #
104 105 NOT_YET_KMODS = $(OLDPTY_OBJS) $(PTY_OBJS) $(VCONS_CONF_OBJS) $(MOD_OBJS)
105 106
106 107 #
107 108 # ----- END OF TRANSITIONAL SECTION -------------------------------------------
108 109 #
109 110 # Include machine independent rules. Note that this does not imply
110 111 # that the resulting module from rules in Makefile.uts is machine
111 112 # independent. Only that the build rules are machine independent.
112 113 #
113 114 include $(UTSBASE)/Makefile.uts
114 115
115 116 #
116 117 # machine specific optimization, override default in Makefile.master
117 118 #
118 119 XARCH_32 = -xarch=v8
119 120 XARCH_64 = -m64
120 121 XARCH = $(XARCH_$(CLASS))
121 122
122 123 COPTIMIZE_32 = -xO3
123 124 COPTIMIZE_64 = -xO3
124 125 COPTIMIZE = $(COPTIMIZE_$(CLASS))
125 126
126 127 CCMODE = -Xa
127 128
128 129 CFLAGS_32 = -xcg92
129 130 CFLAGS_64 = -xchip=ultra $(CCABS32) $(CCREGSYM)
130 131 CFLAGS = $(CFLAGS_$(CLASS))
131 132
132 133 CFLAGS += $(XARCH)
133 134 CFLAGS += $(COPTIMIZE)
134 135 CFLAGS += $(EXTRA_CFLAGS)
135 136 CFLAGS += $(XAOPT)
136 137 CFLAGS += $(INLINES) -D_ASM_INLINES
137 138 CFLAGS += $(CCMODE)
138 139 CFLAGS += $(SPACEFLAG)
139 140 CFLAGS += $(CERRWARN)
140 141 CFLAGS += $(CTF_FLAGS_$(CLASS))
141 142 CFLAGS += $(CSTD)
142 143 CFLAGS += $(CCUNBOUND)
143 144 CFLAGS += $(CCSTATICSYM)
144 145 CFLAGS += $(CC32BITCALLERS)
145 146 CFLAGS += $(CCNOAUTOINLINE)
146 147 CFLAGS += $(IROPTFLAG)
147 148 CFLAGS += $(CGLOBALSTATIC)
148 149 CFLAGS += -xregs=no%float
149 150 CFLAGS += -xstrconst
150 151 CFLAGS += $(CSOURCEDEBUGFLAGS)
151 152 CFLAGS += $(CUSERFLAGS)
152 153
153 154 ASFLAGS += $(XARCH)
154 155
155 156 LINT_DEFS_32 =
156 157 LINT_DEFS_64 = -m64
157 158 LINT_DEFS += $(LINT_DEFS_$(CLASS))
158 159
159 160 #
160 161 # The following must be defined for all implementations:
161 162 #
162 163 # MODSTUBS: Module stubs source file.
163 164 #
164 165 MODSTUBS = $(UTSBASE)/sparc/ml/modstubs.s
165 166
166 167 #
167 168 # Define the actual specific platforms - obviously none.
168 169 #
169 170 MACHINE_DEFS =
170 171
171 172 #
172 173 # Debugging level
173 174 #
174 175 # Special knowledge of which special debugging options effect which
175 176 # file is used to optimize the build if these flags are changed.
176 177 #
177 178 # XXX: The above could possibly be done for more flags and files, but
178 179 # is left as an experiment to the interested reader. Be forewarned,
179 180 # that excessive use could lead to maintenance difficulties.
180 181 #
181 182 DEBUG_DEFS_OBJ32 =
182 183 DEBUG_DEFS_DBG32 = -DDEBUG
183 184 DEBUG_DEFS_OBJ64 =
184 185 DEBUG_DEFS_DBG64 = -DDEBUG
185 186 DEBUG_DEFS = $(DEBUG_DEFS_$(BUILD_TYPE))
186 187
187 188 DEBUG_COND_OBJ32 = $(POUND_SIGN)
188 189 DEBUG_COND_DBG32 =
189 190 DEBUG_COND_OBJ64 = $(POUND_SIGN)
190 191 DEBUG_COND_DBG64 =
191 192 IF_DEBUG_OBJ = $(DEBUG_COND_$(BUILD_TYPE))$(OBJS_DIR)/
192 193
193 194 $(IF_DEBUG_OBJ)syscall.o := DEBUG_DEFS += -DSYSCALLTRACE
194 195 $(IF_DEBUG_OBJ)clock.o := DEBUG_DEFS += -DKSLICE=1
↓ open down ↓ |
160 lines elided |
↑ open up ↑ |
195 196
196 197 # Comment these out if you don't want dispatcher lock statistics.
197 198
198 199 # $(IF_DEBUG_OBJ)disp_lock.o := DEBUG_DEFS += -DDISP_LOCK_STATS
199 200
200 201 #
201 202 # Collect the preprocessor definitions to be associated with *all*
202 203 # files.
203 204 #
204 205 ALL_DEFS = $(MACHINE_DEFS) $(DEBUG_DEFS) $(OPTION_DEFS)
206 +
205 207 #
208 +# TCP congestion control modules (/kernel/cc)
206 209 #
210 +MISC_KMODS += cc
211 +CC_KMODS += cc_newreno cc_cubic cc_sunreno
212 +
213 +#
214 +#
207 215 # The kernels modules which are "implementation architecture"
208 216 # specific for this machine are enumerated below. Note that most
209 217 # of these modules must exist (in one form or another) for each
210 218 # architecture.
211 219 #
212 220 # Common Drivers (usually pseudo drivers) (/kernel/drv):
213 221 #
214 222 DRV_KMODS += aggr arp audio bl blkdev bofi clone cn conskbd consms cpuid
215 223 DRV_KMODS += crypto cryptoadm devinfo dump
216 224 DRV_KMODS += dtrace fasttrap fbt lockstat profile sdt systrace dcpc
217 225 DRV_KMODS += fssnap icmp icmp6 ip ip6 ipnet ipsecah
218 226 DRV_KMODS += ipsecesp iptun iwscn keysock kmdb kstat ksyms llc1
219 227 DRV_KMODS += lofi
220 228 DRV_KMODS += log logindmux kssl mm nca physmem pm poll pool
221 229 DRV_KMODS += pseudo ptc ptm pts ptsl ramdisk random rsm rts sad
222 230 DRV_KMODS += simnet softmac sppp sppptun sy sysevent sysmsg
223 231 DRV_KMODS += spdsock
224 232 DRV_KMODS += tcp tcp6 timerfd tl tnf ttymux udp udp6 wc winlock zcons
225 233 DRV_KMODS += ippctl
226 234 DRV_KMODS += dld
227 235 DRV_KMODS += ipd
228 236 DRV_KMODS += ipf
229 237 DRV_KMODS += rpcib
230 238 DRV_KMODS += dlpistub
231 239 DRV_KMODS += vnic
232 240 DRV_KMODS += xge
233 241 DRV_KMODS += rds
234 242 DRV_KMODS += rdsv3
235 243 DRV_KMODS += chxge
236 244 DRV_KMODS += smbsrv
237 245 DRV_KMODS += vscan
238 246 DRV_KMODS += nsmb
239 247 DRV_KMODS += fm
240 248 DRV_KMODS += nulldriver
241 249 DRV_KMODS += bridge trill
242 250 DRV_KMODS += bpf
243 251 DRV_KMODS += dca
244 252 DRV_KMODS += eventfd
245 253 DRV_KMODS += signalfd
246 254 DRV_KMODS += ufm
247 255 DRV_KMODS += ufmtest
248 256
249 257 #
250 258 # Hardware Drivers in common space
251 259 #
252 260
253 261 DRV_KMODS += afe
254 262 DRV_KMODS += audio1575
255 263 DRV_KMODS += audioens
256 264 DRV_KMODS += audiols
257 265 DRV_KMODS += audiop16x
258 266 DRV_KMODS += audiopci
259 267 DRV_KMODS += audiots
260 268 DRV_KMODS += bnxe
261 269 DRV_KMODS += e1000g
262 270 DRV_KMODS += efe
263 271 DRV_KMODS += hxge
264 272 DRV_KMODS += mxfe
265 273 DRV_KMODS += rge
266 274 DRV_KMODS += rtls
267 275 DRV_KMODS += sfe
268 276 DRV_KMODS += aac
269 277 DRV_KMODS += igb
270 278 DRV_KMODS += ixgbe
271 279 DRV_KMODS += vr
272 280 DRV_KMODS += mr_sas
273 281 DRV_KMODS += yge
274 282
275 283 #
276 284 # Machine Specific Driver Modules (/kernel/drv):
277 285 #
278 286 DRV_KMODS += audiocs
279 287 DRV_KMODS += bge dmfe eri fas hme qfe
280 288 DRV_KMODS += openeepr options sd ses st
281 289 DRV_KMODS += ssd
282 290 DRV_KMODS += ecpp
283 291 DRV_KMODS += hid hubd ehci ohci uhci usb_mid usb_ia scsa2usb usbprn ugen
284 292 DRV_KMODS += usbser usbsacm usbsksp usbsprl
285 293 DRV_KMODS += usb_as usb_ac
286 294 DRV_KMODS += usbskel
287 295 DRV_KMODS += usbvc
288 296 DRV_KMODS += usbftdi
289 297 DRV_KMODS += usbecm
290 298 DRV_KMODS += hci1394 av1394 scsa1394 dcam1394
291 299 DRV_KMODS += sbp2
292 300 DRV_KMODS += ib ibp eibnx eoib rdsib sdp iser daplt hermon tavor sol_ucma sol_uverbs
293 301 DRV_KMODS += sol_umad
294 302 DRV_KMODS += pci_pci pcieb pcieb_bcm
295 303 DRV_KMODS += i8042 kb8042 mouse8042
296 304 DRV_KMODS += fcode
297 305 DRV_KMODS += mpt_sas
298 306 DRV_KMODS += socal
299 307 DRV_KMODS += sgen
300 308 DRV_KMODS += myri10ge
301 309 DRV_KMODS += smp
302 310 DRV_KMODS += dad
303 311 DRV_KMODS += scsi_vhci
304 312 DRV_KMODS += fcp
305 313 DRV_KMODS += fcip
306 314 DRV_KMODS += fcsm
307 315 DRV_KMODS += fp
308 316 DRV_KMODS += qlc
309 317 DRV_KMODS += qlge
310 318 DRV_KMODS += stmf
311 319 DRV_KMODS += stmf_sbd
312 320 DRV_KMODS += fct
313 321 DRV_KMODS += fcoe
314 322 DRV_KMODS += fcoet
315 323 DRV_KMODS += fcoei
316 324 DRV_KMODS += qlt
317 325 DRV_KMODS += iscsit
318 326 DRV_KMODS += pppt
319 327 DRV_KMODS += iscsi
320 328 DRV_KMODS += emlxs
321 329 DRV_KMODS += oce
322 330 DRV_KMODS += srpt
323 331 DRV_KMODS += pmcs
324 332 DRV_KMODS += pmcs8001fw
325 333
326 334 #
327 335 # I/O framework test drivers
328 336 #
329 337 DRV_KMODS += pshot
330 338 DRV_KMODS += gen_drv
331 339 DRV_KMODS += tvhci tphci tclient
332 340 DRV_KMODS += emul64
333 341
334 342 #
335 343 # PCMCIA specific module(s)
336 344 #
337 345 DRV_KMODS += pcs
338 346 MISC_KMODS += busra cardbus dada pcmcia
339 347 DRV_KMODS += pcic
340 348
341 349 #
342 350 # Exec Class Modules (/kernel/exec):
343 351 #
344 352 EXEC_KMODS += aoutexec elfexec intpexec shbinexec javaexec
345 353
346 354 #
347 355 # Scheduling Class Modules (/kernel/sched):
348 356 #
349 357 SCHED_KMODS += RT TS RT_DPTBL TS_DPTBL IA FSS FX FX_DPTBL SDC
350 358
351 359 #
352 360 # File System Modules (/kernel/fs):
353 361 #
354 362 FS_KMODS += dev devfs fdfs fifofs hsfs lofs namefs nfs pcfs tmpfs zfs
355 363 FS_KMODS += zut specfs udfs ufs autofs procfs sockfs mntfs
356 364 FS_KMODS += ctfs objfs sharefs dcfs smbfs bootfs
357 365
358 366 #
359 367 # Streams Modules (/kernel/strmod):
360 368 #
361 369 STRMOD_KMODS += bufmod connld dedump ldterm ms pckt pfmod
362 370 STRMOD_KMODS += pipemod ptem redirmod rpcmod rlmod telmod timod
363 371 STRMOD_KMODS += spppasyn spppcomp
364 372 STRMOD_KMODS += tirdwr ttcompat
365 373 STRMOD_KMODS += usbkbm usbms usbwcm usb_ah
366 374 STRMOD_KMODS += drcompat
367 375 STRMOD_KMODS += cryptmod
368 376 STRMOD_KMODS += vuid3ps2
369 377
370 378 #
371 379 # 'System' Modules (/kernel/sys):
372 380 #
373 381 SYS_KMODS += c2audit
374 382 SYS_KMODS += exacctsys
375 383 SYS_KMODS += inst_sync kaio msgsys semsys shmsys sysacct pipe
376 384 SYS_KMODS += doorfs pset acctctl portfs
377 385
378 386 #
379 387 # 'User' Modules (/kernel/misc):
380 388 #
381 389 MISC_KMODS += ac97
382 390 MISC_KMODS += bignum
383 391 MISC_KMODS += consconfig gld ipc nfs_dlboot nfssrv scsi
384 392 MISC_KMODS += strplumb swapgeneric tlimod
385 393 MISC_KMODS += rpcsec rpcsec_gss kgssapi kmech_dummy
386 394 MISC_KMODS += kmech_krb5
387 395 MISC_KMODS += fssnap_if
388 396 MISC_KMODS += hidparser kbtrans usba usba10 usbs49_fw
389 397 MISC_KMODS += s1394
390 398 MISC_KMODS += hpcsvc pcihp
391 399 MISC_KMODS += rsmops
392 400 MISC_KMODS += sata
393 401 MISC_KMODS += kcf
394 402 MISC_KMODS += ksocket
395 403 MISC_KMODS += ibcm
396 404 MISC_KMODS += ibdm
397 405 MISC_KMODS += ibdma
398 406 MISC_KMODS += ibmf
399 407 MISC_KMODS += ibtl
400 408 MISC_KMODS += sol_ofs
401 409 MISC_KMODS += idm
402 410 MISC_KMODS += idmap
403 411 MISC_KMODS += hook
404 412 MISC_KMODS += neti
405 413 MISC_KMODS += ctf
406 414 MISC_KMODS += mac dls
407 415 MISC_KMODS += cmlb
408 416 MISC_KMODS += tem
409 417 MISC_KMODS += pcicfg fcodem fcpci
410 418 MISC_KMODS += scsi_vhci_f_sym scsi_vhci_f_tpgs
411 419 MISC_KMODS += scsi_vhci_f_sym_hds
412 420 MISC_KMODS += scsi_vhci_f_tape scsi_vhci_f_tpgs_tape
413 421 MISC_KMODS += fctl
414 422 MISC_KMODS += emlxs_fw
415 423 MISC_KMODS += qlc_fw_2200
416 424 MISC_KMODS += qlc_fw_2300
417 425 MISC_KMODS += qlc_fw_2400
418 426 MISC_KMODS += qlc_fw_2500
419 427 MISC_KMODS += qlc_fw_6322
420 428 MISC_KMODS += qlc_fw_8100
421 429 MISC_KMODS += mii
422 430
423 431 MISC_KMODS += klmmod klmops
424 432
425 433 #
426 434 # Software Cryptographic Providers (/kernel/crypto):
427 435 #
428 436 CRYPTO_KMODS += aes
429 437 CRYPTO_KMODS += arcfour
430 438 CRYPTO_KMODS += blowfish
431 439 CRYPTO_KMODS += des
432 440 CRYPTO_KMODS += ecc
433 441 CRYPTO_KMODS += edonr
434 442 CRYPTO_KMODS += md4
435 443 CRYPTO_KMODS += md5
436 444 CRYPTO_KMODS += rsa
437 445 CRYPTO_KMODS += sha1
438 446 CRYPTO_KMODS += sha2
439 447 CRYPTO_KMODS += skein
440 448 CRYPTO_KMODS += swrand
441 449
442 450 #
443 451 # IP Policy Modules (/kernel/ipp):
444 452 #
445 453 IPP_KMODS += dlcosmk
446 454 IPP_KMODS += flowacct
447 455 IPP_KMODS += ipgpc
448 456 IPP_KMODS += dscpmk
449 457 IPP_KMODS += tokenmt
450 458 IPP_KMODS += tswtclmt
451 459
452 460 #
453 461 # 'Dacf' modules (/kernel/dacf)
454 462 DACF_KMODS += consconfig_dacf
455 463
456 464 #
457 465 # SVVS Testing Modules (/kernel/strmod):
458 466 #
459 467 # These are streams and driver modules which are not to be
460 468 # delivered with a released system. However, during development
461 469 # it is convenient to build and install the SVVS kernel modules.
462 470 #
463 471 SVVS_KMODS += lmodb lmode lmodr lmodt svvslo tidg tivc tmux
464 472
465 473 #
466 474 # Modules eXcluded from the product:
467 475 #
468 476 XMODS +=
469 477
470 478 #
471 479 # 'Dacf' Modules (/kernel/dacf):
472 480 #
473 481 DACF_KMODS += net_dacf
474 482
475 483 #
476 484 # MAC-Type Plugin Modules (/kernel/mac)
477 485 #
478 486 MAC_KMODS += mac_6to4
479 487 MAC_KMODS += mac_ether
480 488 MAC_KMODS += mac_ipv4
481 489 MAC_KMODS += mac_ipv6
482 490 MAC_KMODS += mac_wifi
483 491 MAC_KMODS += mac_ib
484 492
485 493 #
486 494 # socketmod (kernel/socketmod)
487 495 #
488 496 SOCKET_KMODS += sockpfp
489 497 SOCKET_KMODS += socksctp
490 498 SOCKET_KMODS += socksdp
491 499 SOCKET_KMODS += sockrds
492 500 SOCKET_KMODS += ksslf
493 501
494 502 #
495 503 # kiconv modules (/kernel/kiconv):
496 504 #
497 505 KICONV_KMODS += kiconv_emea kiconv_ja kiconv_ko kiconv_sc kiconv_tc
498 506
499 507 #
500 508 # Ensure that the variable member of the cpu_t (cpu_m) is defined
501 509 # for the lint builds so as not to cause lint errors during the
502 510 # global cross check.
503 511 #
504 512 $(LINTFLAGSUPPRESS)LINTFLAGS += -D_MACHDEP -I$(UTSBASE)/sun4 \
505 513 -I$(UTSBASE)/sun4u -I$(UTSBASE)/sfmmu
↓ open down ↓ |
289 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX